Skip to content

Allow use of semaphore posting with noexcept #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/boost/interprocess/sync/interprocess_semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/interprocess/sync/detail/common_algorithms.hpp>

#include <system_error>

#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \
defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES)
Expand Down Expand Up @@ -74,6 +76,11 @@ class interprocess_semaphore
//!its wait function. If there is an error an interprocess_exception exception is thrown.
void post();

//!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting
//!for the interprocess_semaphore, then one of these processes will return successfully from
//!its wait function. If there is an error, it'll return a non-null error code.
std::error_code post(const std::nothrow_t &) noexcept;

//!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero,
//!then the calling process/thread blocks until it can decrement the counter.
//!If there is an error an interprocess_exception exception is thrown.
Expand Down Expand Up @@ -135,6 +142,10 @@ inline bool interprocess_semaphore::timed_wait(const TimePoint &abs_time)
inline void interprocess_semaphore::post()
{ m_sem.post(); }

std::error_code interprocess_semaphore::post(const std::nothrow_t &) noexcept {
return m_sem.post(std::nothrow) ;
}

} //namespace interprocess {
} //namespace boost {

Expand Down
11 changes: 11 additions & 0 deletions include/boost/interprocess/sync/named_semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/interprocess_tester.hpp>

#include <system_error>

#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES)
#include <boost/interprocess/sync/posix/named_semaphore.hpp>
//Experimental...
Expand Down Expand Up @@ -116,6 +118,11 @@ class named_semaphore
//!its wait function. If there is an error an interprocess_exception exception is thrown.
void post();

//!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting
//!for the interprocess_semaphore, then one of these processes will return successfully from
//!its wait function. If there is an error, it'll return a non-null error code.
std::error_code post(std::nothrow_t &) noexcept;

//!Decrements the semaphore. If the semaphore value is not greater than zero,
//!then the calling process/thread blocks until it can decrement the counter.
//!If there is an error an interprocess_exception exception is thrown.
Expand Down Expand Up @@ -211,6 +218,10 @@ inline void named_semaphore::wait()
inline void named_semaphore::post()
{ m_sem.post(); }

inline std::error_code named_semaphore::post(std::nothrow_t &) noexcept
{ return m_sem.post(std::nothrow); }


inline bool named_semaphore::try_wait()
{ return m_sem.try_wait(); }

Expand Down
9 changes: 9 additions & 0 deletions include/boost/interprocess/sync/posix/named_semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#include <boost/interprocess/sync/posix/semaphore_wrapper.hpp>

#include <system_error>

namespace boost {
namespace interprocess {

Expand Down Expand Up @@ -59,6 +61,13 @@ class posix_named_semaphore
void post()
{ semaphore_post(mp_sem); }

std::error_code post(const std::nothrow_t &) noexcept {
if (sem_post(mp_sem) != 0) {
return {errno, std::system_category()};
}
return {0, std::system_category()};
}

void wait()
{ semaphore_wait(mp_sem); }

Expand Down
9 changes: 9 additions & 0 deletions include/boost/interprocess/sync/posix/semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#include <boost/interprocess/sync/posix/semaphore_wrapper.hpp>

#include <system_error>

namespace boost {
namespace interprocess {
namespace ipcdetail {
Expand All @@ -44,6 +46,13 @@ class posix_semaphore
void post()
{ semaphore_post(&m_sem); }

std::error_code post(std::nothrow_t &) noexcept {
if (sem_post(&m_sem) != 0) {
return {errno, std::system_category()};
}
return {0, std::system_category()};
}

void wait()
{ semaphore_wait(&m_sem); }

Expand Down
9 changes: 9 additions & 0 deletions include/boost/interprocess/sync/shm/named_semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>

#include <system_error>

namespace boost {
namespace interprocess {
namespace ipcdetail {
Expand Down Expand Up @@ -64,6 +66,8 @@ class shm_named_semaphore
~shm_named_semaphore();

void post();
std::error_code post(std::nothrow_t &) noexcept;

void wait();
bool try_wait();
template<class TimePoint> bool timed_wait(const TimePoint &abs_time);
Expand Down Expand Up @@ -169,6 +173,11 @@ inline shm_named_semaphore::shm_named_semaphore
inline void shm_named_semaphore::post()
{ semaphore()->post(); }

std::error_code shm_named_semaphore::post(std::nothrow_t &) noexcept {
post();
return {0, std::generic_category()};
}

inline void shm_named_semaphore::wait()
{ semaphore()->wait(); }

Expand Down
9 changes: 9 additions & 0 deletions include/boost/interprocess/sync/spin/semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/cstdint.hpp>

#include <system_error>

namespace boost {
namespace interprocess {
namespace ipcdetail {
Expand All @@ -41,6 +43,8 @@ class spin_semaphore
~spin_semaphore();

void post();
std::error_code post(const std::nothrow_t &) noexcept;

void wait();
bool try_wait();
template<class TimePoint> bool timed_wait(const TimePoint &abs_time);
Expand All @@ -62,6 +66,11 @@ inline void spin_semaphore::post()
ipcdetail::atomic_inc32(&m_count);
}

inline std::error_code spin_semaphore::post(const std::nothrow_t &) noexcept {
post();
return {0, std::system_category()};
}

inline void spin_semaphore::wait()
{
ipcdetail::lock_to_wait<spin_semaphore> lw(*this);
Expand Down
19 changes: 18 additions & 1 deletion include/boost/interprocess/sync/windows/named_semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
#include <boost/interprocess/sync/windows/named_sync.hpp>
#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>

extern "C" {
#include <errhandlingapi.h>
}

#include <system_error>

namespace boost {
namespace interprocess {
namespace ipcdetail {
Expand Down Expand Up @@ -59,6 +65,7 @@ class winapi_named_semaphore
~winapi_named_semaphore();

void post();
std::error_code post(const std::nothrow_t &) noexcept;
void wait();
bool try_wait();
template<class TimePoint> bool timed_wait(const TimePoint &abs_time);
Expand Down Expand Up @@ -192,9 +199,19 @@ inline winapi_named_semaphore::winapi_named_semaphore(open_only_t, const wchar_t

inline void winapi_named_semaphore::post()
{
m_sem_wrapper.post();
if (m_sem_wrapper.post() == 0) {
throw interprocess_exception(GetLastError());
}
}

inline std::error_code winapi_named_semaphore::post(const std::nothrow_t &) noexcept {
if (m_sem_wrapper.post() == 0) {
return {GetLastError(), std::system_category()};
};
return {0, std::system_category()};
}


inline void winapi_named_semaphore::wait()
{
m_sem_wrapper.wait();
Expand Down
19 changes: 18 additions & 1 deletion include/boost/interprocess/sync/windows/semaphore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/assert.hpp>

extern "C" {
#include <errhandlingapi.h>
}
#include <system_error>

namespace boost {
namespace interprocess {
Expand All @@ -43,6 +47,7 @@ class winapi_semaphore
~winapi_semaphore();

void post(unsigned int release_count = 1);
std::error_code post(const std::nothrow_t&);
void wait();
bool try_wait();
template<class TimePoint> bool timed_wait(const TimePoint &abs_time);
Expand Down Expand Up @@ -106,7 +111,19 @@ inline void winapi_semaphore::post(unsigned release_count)
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_));
sem.post(static_cast<long>(release_count));
if (sem.post(static_cast<long>(release_count)) == 0) {
throw interprocess_exception(GetLastError());
}
}

std::error_code post(const std::nothrow_t&) {
sync_handles &handles =
windows_intermodule_singleton<sync_handles>::get();
winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, this, initial_count_));
if (sem.post(static_cast<long>(release_count)) == 0) {
return {GetLastError(), std::system_category()} ;
}
return {0, std::system_category()};
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ class winapi_semaphore_functions
: m_sem_hnd(hnd)
{}

void post(long count = 1)
int post(long count = 1)
{
long prev_count;
winapi::release_semaphore(m_sem_hnd, count, &prev_count);
return winapi::release_semaphore(m_sem_hnd, count, &prev_count);
}

void wait()
Expand Down
8 changes: 8 additions & 0 deletions test/semaphore_test_template.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ inline int test_all_semaphore()
test::test_all_lock<semaphore_test_wrapper<Semaphore> >();
test::test_all_recursive_lock<recursive_semaphore_test_wrapper<Semaphore> >();
test::test_all_mutex<semaphore_test_wrapper<Semaphore> >();

Semaphore s(0);
BOOST_INTERPROCESS_CHECK(!s.try_wait());
BOOST_INTERPROCESS_CHECK(!s.post(std::nothrow));
BOOST_INTERPROCESS_CHECK(s.try_wait());
// TODO: not trivial to simulate failure as that would require
// failure injection (augmenting implementations for test mode)

return 0;
}

Expand Down