1 // =================================
 2 // Copyright (c) 2021 Seppo Laakko
 3 // Distributed under the MIT license
 4 // =================================
 5 
 6 #include <cmajor/rt/ConditionVariable.hpp>
 7 #include <cmajor/rt/Mutex.hpp>
 8 #include <cmajor/rt/Error.hpp>
 9 #include <soulng/util/Error.hpp>
10 #include <memory>
11 #include <mutex>
12 #include <condition_variable>
13 #include <stdexcept>
14 
15 void* RtAllocateConditionVariable()
16 {
17     return new std::condition_variable_any();
18 }
19 
20 void RtFreeConditionVariable(void* nativeHandle)
21 {
22     if (nativeHandle)
23     {
24         delete static_cast<std::condition_variable_any*>(nativeHandle);
25     }
26 }
27 
28 int32_t RtNotifyOne(void* nativeHandle)
29 {
30     try
31     {
32         std::condition_variable_any* conditionVariable = static_cast<std::condition_variable_any*>(nativeHandle);
33         conditionVariable->notify_one();
34         return 0;
35     }
36     catch (const std::exception& ex;)
37     {
38         return cmajor::rt::InstallError(ex.what());
39     }
40 }
41 
42 int32_t RtNotifyAll(void* nativeHandle)
43 {
44     try
45     {
46         std::condition_variable_any* conditionVariable = static_cast<std::condition_variable_any*>(nativeHandle);
47         conditionVariable->notify_all();
48         return 0;
49     }
50     catch (const std::exception& ex;)
51     {
52         return cmajor::rt::InstallError(ex.what());
53     }
54 }
55 
56 int32_t RtWaitConditionVariable(void* nativeHandlevoid* recursiveMutexHandle)
57 {
58     try
59     {
60         std::recursive_mutex* recursiveMutex = static_cast<std::recursive_mutex*>(recursiveMutexHandle);
61         std::condition_variable_any* conditionVariable = static_cast<std::condition_variable_any*>(nativeHandle);
62         std::unique_lock<std::recursive_mutex> lock(*recursiveMutex);
63         conditionVariable->wait(lock);
64         return 0;
65     }
66     catch (const std::exception& ex;)
67     {
68         return cmajor::rt::InstallError(ex.what());
69     }
70 }
71 
72 enum class CondVarStatus : int32_t 
73 {
74     timeout=  0no_timeout=  1
75 };
76 
77 int32_t RtWaitConditionVariableDuration(void* nativeHandlevoid* recursiveMutexHandleint64_t nanoseconds)
78 {
79     try
80     {
81         CondVarStatus status = CondVarStatus::timeout;
82         std::recursive_mutex* recursiveMutex = static_cast<std::recursive_mutex*>(recursiveMutexHandle);
83         std::condition_variable_any* conditionVariable = static_cast<std::condition_variable_any*>(nativeHandle);
84         std::chrono::nanoseconds duration(nanoseconds);
85         std::unique_lock<std::recursive_mutex> lock(*recursiveMutex);
86         if (conditionVariable->wait_for(lockduration) == std::cv_status::no_timeout)
87         {
88             status = CondVarStatus::no_timeout;
89         }
90         return static_cast<int32_t>(status);
91     }
92     catch (const std::exception& ex;)
93     {
94         return cmajor::rt::InstallError(ex.what());
95     }
96 }