XBT_PUBLIC void intrusive_ptr_add_ref(ActivityImpl* activity);
XBT_PUBLIC void intrusive_ptr_release(ActivityImpl* activity);
+ class ConditionVariableImpl;
+
class CommImpl;
using CommImplPtr = boost::intrusive_ptr<CommImpl>;
class ExecImpl;
typedef simgrid::kernel::context::Context* smx_context_t;
typedef simgrid::kernel::actor::ActorImpl* smx_actor_t;
+typedef simgrid::kernel::activity::ConditionVariableImpl* smx_cond_t;
typedef simgrid::kernel::activity::MutexImpl* smx_mutex_t;
typedef simgrid::kernel::activity::MailboxImpl* smx_mailbox_t;
typedef simgrid::surf::StorageImpl* surf_storage_t;
typedef struct s_smx_context* smx_context_t;
typedef struct s_smx_actor* smx_actor_t;
+typedef struct s_smx_cond_t* smx_cond_t;
typedef struct s_smx_mutex* smx_mutex_t;
typedef struct s_smx_mailbox* smx_mailbox_t;
typedef struct s_surf_storage* surf_storage_t;
*/
class XBT_PUBLIC ConditionVariable {
private:
- friend s_smx_cond_t;
+ friend kernel::activity::ConditionVariableImpl;
smx_cond_t cond_;
explicit ConditionVariable(smx_cond_t cond) : cond_(cond) {}
public:
/* ******************************** Synchro ************************************ */
-/**
- * \ingroup simix_synchro_management
- */
-typedef struct s_smx_cond_t* smx_cond_t;
/**
* \ingroup simix_synchro_management
*/
XBT_PUBLIC void simcall_mutex_unlock(smx_mutex_t mutex);
XBT_PUBLIC smx_cond_t simcall_cond_init();
-XBT_PUBLIC void SIMIX_cond_unref(smx_cond_t cond);
-XBT_PUBLIC smx_cond_t SIMIX_cond_ref(smx_cond_t cond);
XBT_PUBLIC void simcall_cond_signal(smx_cond_t cond);
XBT_PUBLIC void simcall_cond_wait(smx_cond_t cond, smx_mutex_t mutex);
XBT_PUBLIC void simcall_cond_wait_timeout(smx_cond_t cond, smx_mutex_t mutex, double max_duration);
#ifndef XBT_THREAD_H
#define XBT_THREAD_H
+#include "simgrid/forward.h"
#include <xbt/function_types.h>
#include <xbt/misc.h> /* SG_BEGIN_DECL */
/** @brief Thread condition data type (opaque object)
* @hideinitializer
*/
+#ifdef __cplusplus
+typedef simgrid::kernel::activity::ConditionVariableImpl* xbt_cond_t;
+#else
typedef struct s_smx_cond_* xbt_cond_t;
+#endif
/** @brief Creates a condition variable */
XBT_PUBLIC xbt_cond_t xbt_cond_init(void);
smx_cond_t SIMIX_cond_init()
{
XBT_IN("()");
- smx_cond_t cond = new s_smx_cond_t();
+ smx_cond_t cond = new simgrid::kernel::activity::ConditionVariableImpl();
XBT_OUT();
return cond;
}
XBT_OUT();
}
+namespace simgrid {
+namespace kernel {
+namespace activity {
+
+ConditionVariableImpl::ConditionVariableImpl() : cond_(this) {}
+ConditionVariableImpl::~ConditionVariableImpl() = default;
+
/**
* \brief Signalizes a condition.
*
* If there are no process sleeping, no action is done.
* \param cond A condition
*/
-void SIMIX_cond_signal(smx_cond_t cond)
+void ConditionVariableImpl::signal()
{
- XBT_IN("(%p)", cond);
- XBT_DEBUG("Signal condition %p", cond);
+ XBT_DEBUG("Signal condition %p", this);
/* If there are processes waiting for the condition choose one and try
to make it acquire the mutex */
- if (not cond->sleeping.empty()) {
- auto& proc = cond->sleeping.front();
- cond->sleeping.pop_front();
+ if (not sleeping.empty()) {
+ auto& proc = sleeping.front();
+ sleeping.pop_front();
/* Destroy waiter's synchronization */
proc.waiting_synchro = nullptr;
*
* Signal ALL processes waiting on a condition.
* If there are no process waiting, no action is done.
- * \param cond A condition
*/
-void SIMIX_cond_broadcast(smx_cond_t cond)
+void ConditionVariableImpl::broadcast()
{
- XBT_IN("(%p)", cond);
- XBT_DEBUG("Broadcast condition %p", cond);
+ XBT_DEBUG("Broadcast condition %p", this);
/* Signal the condition until nobody is waiting on it */
- while (not cond->sleeping.empty()) {
- SIMIX_cond_signal(cond);
- }
- XBT_OUT();
+ while (not sleeping.empty())
+ signal();
}
-smx_cond_t SIMIX_cond_ref(smx_cond_t cond)
+// boost::intrusive_ptr<ConditionVariableImpl> support:
+void intrusive_ptr_add_ref(simgrid::kernel::activity::ConditionVariableImpl* cond)
{
- if (cond != nullptr)
- intrusive_ptr_add_ref(cond);
- return cond;
+ cond->refcount_.fetch_add(1, std::memory_order_relaxed);
}
-void SIMIX_cond_unref(smx_cond_t cond)
+void intrusive_ptr_release(simgrid::kernel::activity::ConditionVariableImpl* cond)
{
- XBT_IN("(%p)", cond);
- XBT_DEBUG("Destroy condition %p", cond);
- if (cond != nullptr) {
- intrusive_ptr_release(cond);
+ if (cond->refcount_.fetch_sub(1, std::memory_order_release) == 1) {
+ std::atomic_thread_fence(std::memory_order_acquire);
+ xbt_assert(cond->sleeping.empty(), "Cannot destroy conditional since someone is still using it");
+ delete cond;
}
- XBT_OUT();
+}
+} // namespace activity
+} // namespace kernel
}
-void intrusive_ptr_add_ref(s_smx_cond_t* cond)
+XBT_PRIVATE void simcall_HANDLER_cond_signal(smx_simcall_t simcall, smx_cond_t cond)
{
- auto previous = cond->refcount_.fetch_add(1);
- xbt_assert(previous != 0);
+ cond->signal();
}
-void intrusive_ptr_release(s_smx_cond_t* cond)
+XBT_PRIVATE void simcall_HANDLER_cond_broadcast(smx_simcall_t simcall, smx_cond_t cond)
{
- if (cond->refcount_.fetch_sub(1) == 1) {
- xbt_assert(cond->sleeping.empty(), "Cannot destroy conditional since someone is still using it");
- delete cond;
- }
+ cond->broadcast();
}
#include "src/simix/ActorImpl.hpp"
#include <boost/intrusive/list.hpp>
-struct s_smx_cond_t {
- s_smx_cond_t() : cond_(this) {}
+namespace simgrid {
+namespace kernel {
+namespace activity {
+
+class XBT_PUBLIC ConditionVariableImpl {
+public:
+ ConditionVariableImpl();
+ ~ConditionVariableImpl();
- std::atomic_int_fast32_t refcount_{1};
- smx_mutex_t mutex = nullptr;
simgrid::kernel::actor::SynchroList sleeping; /* list of sleeping processes */
+ smx_mutex_t mutex = nullptr;
simgrid::s4u::ConditionVariable cond_;
-};
+ void broadcast();
+ void signal();
+
+private:
+ std::atomic_int_fast32_t refcount_{1};
+ friend void intrusive_ptr_add_ref(ConditionVariableImpl* cond);
+ friend void intrusive_ptr_release(ConditionVariableImpl* cond);
+};
+} // namespace activity
+} // namespace kernel
+} // namespace simgrid
XBT_PRIVATE smx_cond_t SIMIX_cond_init();
-XBT_PRIVATE void SIMIX_cond_broadcast(smx_cond_t cond);
-XBT_PRIVATE void SIMIX_cond_signal(smx_cond_t cond);
-XBT_PRIVATE void intrusive_ptr_add_ref(s_smx_cond_t* cond);
-XBT_PRIVATE void intrusive_ptr_release(s_smx_cond_t* cond);
+
+// simcall handlers
+XBT_PRIVATE void simcall_HANDLER_cond_signal(smx_simcall_t simcall, smx_cond_t cond);
+XBT_PRIVATE void simcall_HANDLER_cond_broadcast(smx_simcall_t simcall, smx_cond_t cond);
#endif
XBT_PRIVATE void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex);
XBT_PRIVATE int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex);
XBT_PRIVATE void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex);
+XBT_PRIVATE void simcall_HANDLER_cond_signal(smx_simcall_t simcall, smx_cond_t cond);
XBT_PRIVATE void simcall_HANDLER_cond_wait(smx_simcall_t simcall, smx_cond_t cond, smx_mutex_t mutex);
XBT_PRIVATE void simcall_HANDLER_cond_wait_timeout(smx_simcall_t simcall, smx_cond_t cond, smx_mutex_t mutex, double timeout);
+XBT_PRIVATE void simcall_HANDLER_cond_broadcast(smx_simcall_t simcall, smx_cond_t cond);
XBT_PRIVATE void simcall_HANDLER_sem_acquire(smx_simcall_t simcall, smx_sem_t sem);
XBT_PRIVATE void simcall_HANDLER_sem_acquire_timeout(smx_simcall_t simcall, smx_sem_t sem, double timeout);
XBT_PRIVATE void simcall_HANDLER_storage_read(smx_simcall_t simcall, surf_storage_t st, sg_size_t size);
inline static void simcall_BODY_cond_signal(smx_cond_t cond)
{
if (0) /* Go to that function to follow the code flow through the simcall barrier */
- SIMIX_cond_signal(cond);
+ simcall_HANDLER_cond_signal(&SIMIX_process_self()->simcall, cond);
return simcall<void, smx_cond_t>(SIMCALL_COND_SIGNAL, cond);
}
inline static void simcall_BODY_cond_broadcast(smx_cond_t cond)
{
if (0) /* Go to that function to follow the code flow through the simcall barrier */
- SIMIX_cond_broadcast(cond);
+ simcall_HANDLER_cond_broadcast(&SIMIX_process_self()->simcall, cond);
return simcall<void, smx_cond_t>(SIMCALL_COND_BROADCAST, cond);
}
break;
case SIMCALL_COND_SIGNAL:
- SIMIX_cond_signal(simgrid::simix::unmarshal<smx_cond_t>(simcall->args[0]));
+ simcall_HANDLER_cond_signal(simcall, simgrid::simix::unmarshal<smx_cond_t>(simcall->args[0]));
SIMIX_simcall_answer(simcall);
break;
break;
case SIMCALL_COND_BROADCAST:
- SIMIX_cond_broadcast(simgrid::simix::unmarshal<smx_cond_t>(simcall->args[0]));
+ simcall_HANDLER_cond_broadcast(simcall, simgrid::simix::unmarshal<smx_cond_t>(simcall->args[0]));
SIMIX_simcall_answer(simcall);
break;
void mutex_unlock(smx_mutex_t mutex);
smx_cond_t cond_init() [[nohandler]];
-void cond_signal(smx_cond_t cond) [[nohandler]];
+void cond_signal(smx_cond_t cond);
void cond_wait(smx_cond_t cond, smx_mutex_t mutex) [[block]];
void cond_wait_timeout(smx_cond_t cond, smx_mutex_t mutex, double timeout) [[block]];
-void cond_broadcast(smx_cond_t cond) [[nohandler]];
+void cond_broadcast(smx_cond_t cond);
void sem_acquire(smx_sem_t sem) [[block]];
void sem_acquire_timeout(smx_sem_t sem, double timeout) [[block]];
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
+#include "simgrid/simix.h" /* used implementation */
+#include "src/kernel/activity/ConditionVariableImpl.hpp"
#include "xbt/ex.hpp"
#include "xbt/synchro.h"
-#include "simgrid/simix.h" /* used implementation */
-
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_sync, xbt, "Synchronization mechanism");
/****** mutex related functions ******/
void xbt_cond_destroy(xbt_cond_t cond)
{
- SIMIX_cond_unref((smx_cond_t)cond);
+ delete cond;
}