Zth (libzth)
4_sync.cpp

Synchronization primitives example. This program will print something like this:

Other fiber
fiber 3 outside of critical section
 { fiber 3 at start of critical section
fiber 2 outside of critical section
fiber 1 outside of critical section
Other fiber
 } fiber 3 at end of critical section
 { fiber 2 at start of critical section
Other fiber
fiber 3 outside of critical section
 } fiber 2 at end of critical section
 { fiber 1 at start of critical section
Other fiber
fiber 2 outside of critical section
 } fiber 1 at end of critical section
 { fiber 3 at start of critical section
Other fiber
fiber 1 outside of critical section
 } fiber 3 at end of critical section
 { fiber 2 at start of critical section
Other fiber
fiber 3 outside of critical section
 } fiber 2 at end of critical section
 { fiber 1 at start of critical section
Other fiber
fiber 2 outside of critical section
 } fiber 1 at end of critical section
 { fiber 3 at start of critical section
Other fiber
fiber 1 outside of critical section
 } fiber 3 at end of critical section
 { fiber 2 at start of critical section
Other fiber
 } fiber 2 at end of critical section
 { fiber 1 at start of critical section
Other fiber
 } fiber 1 at end of critical section
Other fiber
#include <zth>
#include <cstdio>
// Even though all code within a fiber is executed atomically when not yielded,
// sometimes it is required to yield within a (long) critical section anyway.
// If you have many fibers, but only a few may be trying to access the critical
// section, it is still nice to yield. In that case, synchronization
// primitives are required. Zth offers a few, namely a mutex, signal (a.k.a.
// condition), and a semaphore. Their interface is straight-forward. Here, we
// only show an example with a mutex.
static zth::Mutex mutex;
void fiber(int id)
{
for(int i = 0; i < 3; i++) {
printf("fiber %d outside of critical section\n", id);
mutex.lock();
printf(" { fiber %d at start of critical section\n", id);
// It does not matter how and how often we yield, other fibers
// trying to lock the mutex will not be scheduled, but others
// may.
printf(" } fiber %d at end of critical section\n", id);
mutex.unlock();
}
}
static bool stopOther = false;
void otherFiber()
{
while(!stopOther) {
printf("Other fiber\n");
}
}
zth_fiber(otherFiber)
int main_fiber(int /*argc*/, char** /*argv*/)
{
fiber_future f1 = async fiber(1);
fiber_future f2 = async fiber(2);
fiber_future f3 = async fiber(3);
async otherFiber();
f1->wait();
f2->wait();
f3->wait();
stopOther = true;
return 0;
}
Fiber-aware mutex.
Definition: sync.h:340
void lock()
Definition: sync.h:357
void unlock() noexcept
Definition: sync.h:374
int main_fiber(int argc, char **argv)
Definition: main.cpp:14
void outOfWork()
Force a context switch.
Definition: worker.h:457
#define zth_fiber(...)
Prepare every given function to become a fiber by async.
Definition: async.h:765
void yield(Fiber *preferFiber=nullptr, bool alwaysYield=false, Timestamp const &now=Timestamp::now())
Allow a context switch.
Definition: worker.h:435
fiber_type< F >::factory fiber(F f, char const *name=nullptr)
Create a new fiber.
Definition: async.h:713
#define async
Run a function as a new fiber.
Definition: async.h:789