Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
save a cast
[simgrid.git] / src / s4u / s4u_Barrier.cpp
1 /* Copyright (c) 2018-2019. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include <exception>
7 #include <mutex>
8
9 #include "simgrid/Exception.hpp"
10 #include "simgrid/barrier.h"
11 #include "simgrid/s4u/Barrier.hpp"
12 #include "simgrid/simix.h"
13 #include "xbt/log.hpp"
14
15 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_barrier, "S4U barrier");
16
17 namespace simgrid {
18 namespace s4u {
19
20 Barrier::Barrier(unsigned int expected_processes) : mutex_(Mutex::create()), cond_(ConditionVariable::create()), expected_processes_(expected_processes)
21 {
22 }
23
24 /** @brief Create a new barrier
25  *
26  * See @ref s4u_raii.
27  */
28 BarrierPtr Barrier::create(unsigned int expected_processes)
29 {
30     return BarrierPtr(new Barrier(expected_processes));
31 }
32
33 /**
34  * Wait functions
35  */
36 int Barrier::wait()
37 {
38   mutex_->lock();
39   arrived_processes_++;
40   XBT_DEBUG("waiting %p %u/%u", this, arrived_processes_, expected_processes_);
41   if (arrived_processes_ == expected_processes_) {
42     cond_->notify_all();
43     mutex_->unlock();
44     arrived_processes_ = 0;
45     return -1;
46   }
47
48   cond_->wait(mutex_);
49   mutex_->unlock();
50   return 0;
51 }
52
53 void intrusive_ptr_add_ref(Barrier* barrier)
54 {
55   xbt_assert(barrier);
56   barrier->refcount_.fetch_add(1, std::memory_order_relaxed);
57 }
58
59 void intrusive_ptr_release(Barrier* barrier)
60 {
61   xbt_assert(barrier);
62   if (barrier->refcount_.fetch_sub(1, std::memory_order_release) == 1) {
63     std::atomic_thread_fence(std::memory_order_acquire);
64     delete barrier;
65   }
66 }
67 } // namespace s4u
68 } // namespace simgrid
69
70 /* **************************** Public C interface *************************** */
71
72 sg_bar_t sg_barrier_init(unsigned int count)
73 {
74   return new simgrid::s4u::Barrier(count);
75 }
76
77 /** @brief Initializes a barrier, with count elements */
78 void sg_barrier_destroy(sg_bar_t bar)
79 {
80   delete bar;
81 }
82
83 /** @brief Performs a barrier already initialized */
84 int sg_barrier_wait(sg_bar_t bar)
85 {
86   return bar->wait();
87 }