Skip to content

Commit

Permalink
Added macos support
Browse files Browse the repository at this point in the history
  • Loading branch information
danlapid committed Feb 10, 2024
1 parent 51a4bbb commit c4da4c0
Show file tree
Hide file tree
Showing 32 changed files with 575 additions and 61 deletions.
8 changes: 0 additions & 8 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -347,14 +347,6 @@ jobs:
cxxver: 20,
generator: "Unix Makefiles",
}
- {
name: "MacOS 11 C++20",
os: macos-11,
buildtype: Release,
cxx: "clang++",
cxxver: 20,
generator: "Unix Makefiles",
}
- {
name: "MacOS 12 C++20",
os: macos-12,
Expand Down
12 changes: 12 additions & 0 deletions include/cppcoro/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@
# define CPPCORO_OS_LINUX 0
#endif

#if defined(__APPLE__)
# define CPPCORO_OS_DARWIN 1
#else
# define CPPCORO_OS_DARWIN 0
#endif

#if defined(__FreeBSD__)
# define CPPCORO_OS_FREEBSD 1
#else
# define CPPCORO_OS_FREEBSD 0
#endif

/////////////////////////////////////////////////////////////////////////////
// CPU Detection

Expand Down
79 changes: 79 additions & 0 deletions include/cppcoro/detail/darwin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Microsoft
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////
#ifndef CPPCORO_DETAIL_DARWIN_HPP_INCLUDED
#define CPPCORO_DETAIL_DARWIN_HPP_INCLUDED

#include <cppcoro/config.hpp>

#if !CPPCORO_OS_DARWIN
#error <cppcoro/detail/darwin.hpp> is only supported on the Linux platform.
#endif

#include <cstdint>
#include <functional>
#include <sys/event.h>
#include <utility>

namespace cppcoro
{
class io_service;
namespace detail
{
namespace darwin
{
using fd_t = int;

class safe_fd
{
public:
safe_fd();

explicit safe_fd(fd_t fd);
~safe_fd() noexcept;
safe_fd(const safe_fd& other) noexcept;
safe_fd& operator=(const safe_fd& other) noexcept;
safe_fd(safe_fd&& other) noexcept;
safe_fd& operator=(safe_fd&& other) noexcept;
constexpr fd_t fd() const { return m_fd; }
constexpr fd_t handle() const { return m_fd; }
/// Calls close() and sets the fd to -1.
void close() noexcept;
bool operator==(const safe_fd& other) const { return m_fd == other.m_fd; }
bool operator!=(const safe_fd& other) const { return m_fd != other.m_fd; }
bool operator==(fd_t fd) const { return m_fd == fd; }
bool operator!=(fd_t fd) const { return m_fd != fd; }

private:
fd_t m_fd;
};

struct io_state
{
explicit io_state(io_service* ioService) noexcept
: m_ioService(ioService)
, m_fd(-1)
, m_res(0)
, m_completeFunc([] { return 0; })
{
}

std::size_t get_result();
void on_operation_completed_base();
void cancel() noexcept;

io_service* m_ioService;
fd_t m_fd;
std::int32_t m_res;
std::function<int()> m_completeFunc;
};

safe_fd create_timer_fd();
safe_fd create_kqueue_fd();

} // namespace darwin
} // namespace detail
} // namespace cppcoro

#endif
5 changes: 4 additions & 1 deletion include/cppcoro/detail/message_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ namespace cppcoro
void unwatch_handle(file_handle_t handle);
bool enqueue_message(message msg);
bool dequeue_message(message& msg, bool wait);
#if CPPCORO_OS_DARWIN
void watch_event(struct kevent* event, void* cb);
#endif

private:
#if CPPCORO_OS_LINUX
#if CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
int m_pipefd[2];
#endif
safe_file_handle_t m_pollfd;
Expand Down
12 changes: 9 additions & 3 deletions include/cppcoro/detail/platform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@

#include <cppcoro/config.hpp>
#if CPPCORO_OS_WINNT
# include <cppcoro/detail/win32.hpp>
#include <cppcoro/detail/win32.hpp>
#elif CPPCORO_OS_LINUX
# include <cppcoro/detail/linux.hpp>
#include <cppcoro/detail/linux.hpp>
#elif CPPCORO_OS_DARWIN
#include <cppcoro/detail/darwin.hpp>
#endif


namespace cppcoro
{
namespace detail
Expand All @@ -27,6 +28,11 @@ namespace cppcoro
using safe_file_handle_t = linux::safe_fd;
using socket_handle_t = linux::fd_t;
using io_state = linux::io_state;
#elif CPPCORO_OS_DARWIN
using file_handle_t = darwin::fd_t;
using safe_file_handle_t = darwin::safe_fd;
using socket_handle_t = darwin::fd_t;
using io_state = darwin::io_state;
#endif
}
}
Expand Down
2 changes: 1 addition & 1 deletion include/cppcoro/io_service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ namespace cppcoro

};

#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
class io_service::timed_schedule_operation
: public detail::async_operation_cancellable<timed_schedule_operation>
{
Expand Down
4 changes: 2 additions & 2 deletions include/cppcoro/net/socket_recv_from_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace cppcoro::net
: m_socket(socket)
#if CPPCORO_OS_WINNT
, m_buffer(const_cast<void*>(buffer), byteCount)
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
, m_buffer(buffer)
, m_byteCount(byteCount)
#endif
Expand All @@ -46,7 +46,7 @@ namespace cppcoro::net
socket& m_socket;
#if CPPCORO_OS_WINNT
cppcoro::detail::win32::wsabuf m_buffer;
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
void* m_buffer;
std::size_t m_byteCount;
#endif
Expand Down
4 changes: 2 additions & 2 deletions include/cppcoro/net/socket_recv_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace cppcoro::net
: m_socket(s)
#if CPPCORO_OS_WINNT
, m_buffer(const_cast<void*>(buffer), byteCount)
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
, m_buffer(buffer)
, m_byteCount(byteCount)
#endif
Expand All @@ -42,7 +42,7 @@ namespace cppcoro::net
socket& m_socket;
#if CPPCORO_OS_WINNT
cppcoro::detail::win32::wsabuf m_buffer;
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
void* m_buffer;
std::size_t m_byteCount;
#endif
Expand Down
4 changes: 2 additions & 2 deletions include/cppcoro/net/socket_send_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace cppcoro::net
: m_socket(s)
#if CPPCORO_OS_WINNT
, m_buffer(const_cast<void*>(buffer), byteCount)
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
, m_buffer(buffer)
, m_byteCount(byteCount)
#endif
Expand All @@ -42,7 +42,7 @@ namespace cppcoro::net
socket& m_socket;
#if CPPCORO_OS_WINNT
cppcoro::detail::win32::wsabuf m_buffer;
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
const void* m_buffer;
std::size_t m_byteCount;
#endif
Expand Down
4 changes: 2 additions & 2 deletions include/cppcoro/net/socket_send_to_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace cppcoro::net
, m_destination(destination)
#if CPPCORO_OS_WINNT
, m_buffer(const_cast<void*>(buffer), byteCount)
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
, m_buffer(buffer)
, m_byteCount(byteCount)
#endif
Expand All @@ -46,7 +46,7 @@ namespace cppcoro::net
ip_endpoint m_destination;
#if CPPCORO_OS_WINNT
cppcoro::detail::win32::wsabuf m_buffer;
#elif CPPCORO_OS_LINUX
#elif CPPCORO_OS_LINUX || CPPCORO_OS_DARWIN
const void* m_buffer;
std::size_t m_byteCount;
#endif
Expand Down
14 changes: 14 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,20 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
io_service.cpp
)
list(APPEND sources ${linuxSources} ${fileSources} ${socketNetSources})
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
set(darwinDetailIncludes
darwin.hpp
)
list(TRANSFORM darwinDetailIncludes PREPEND "${PROJECT_SOURCE_DIR}/include/cppcoro/detail/")
list(APPEND detailIncludes ${darwinDetailIncludes})
list(APPEND netIncludes ${socketNetIncludes})

set(darwinSources
darwin.cpp
darwin_message_queue.cpp
io_service.cpp
)
list(APPEND sources ${darwinSources} ${fileSources} ${socketNetSources})
endif()

add_library(cppcoro
Expand Down
125 changes: 125 additions & 0 deletions lib/darwin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Microsoft
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////
#include <cppcoro/io_service.hpp>
#include <cppcoro/detail/darwin.hpp>
#include <cassert>
#include <cstring>
#include <errno.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/types.h>
#include <system_error>
#include <unistd.h>

namespace cppcoro
{
namespace detail
{
namespace darwin
{
safe_fd create_timer_fd()
{
int fd = kqueue();

if (fd == -1)
{
throw std::system_error{ static_cast<int>(errno),
std::system_category(),
"Error creating io_service: timer fd create" };
}

return safe_fd{ fd };
}

safe_fd create_kqueue_fd()
{
int fd = kqueue();

if (fd == -1)
{
throw std::system_error{ static_cast<int>(errno),
std::system_category(),
"Error creating timer thread: kqueue create" };
}

return safe_fd{ fd };
}

safe_fd::safe_fd()
: m_fd(-1)
{
}

safe_fd::safe_fd(fd_t fd)
: m_fd(fd)
{
}

safe_fd::~safe_fd() noexcept
{
close();
}

safe_fd::safe_fd(const safe_fd& other) noexcept
: m_fd(dup(other.m_fd))
{
}

safe_fd& safe_fd::operator=(const safe_fd& other) noexcept
{
m_fd = dup(other.m_fd);
return *this;
}

safe_fd::safe_fd(safe_fd&& other) noexcept
: m_fd(std::exchange(other.m_fd, -1))
{
}

safe_fd& safe_fd::operator=(safe_fd&& other) noexcept
{
m_fd = std::exchange(other.m_fd, -1);
return *this;
}

void safe_fd::close() noexcept
{
if (m_fd != -1)
{
::close(m_fd);
m_fd = -1;
}
}

std::size_t io_state::get_result()
{
if (m_res < 0)
{
throw std::system_error{ -m_res, std::system_category() };
}

return m_res;
}

void io_state::on_operation_completed_base()
{
m_ioService->get_io_context().unwatch_handle(m_fd);
m_res = m_completeFunc();
if (m_res < 0)
{
m_res = -errno;
}
}

void io_state::cancel() noexcept
{
m_ioService->get_io_context().unwatch_handle(m_fd);
m_res = -ECANCELED;
m_ioService->get_io_context().enqueue_message(
{ message_type::CALLBACK_TYPE, static_cast<void*>(this) });
}
} // namespace darwin
} // namespace detail
} // namespace cppcoro
Loading

0 comments on commit c4da4c0

Please sign in to comment.