Hi Edward,
Relacy contains rl::mutex/rl::recursive_mutex which are modeled after
std::mutex/recursive_mutex (C++0x). If you do not need timed_wait
functionality then you may use them.
And if you need timed_wait functionality... well, I decided to not
model boost.thread API in this release, because it's one more API and
a lot of additional work.
But boost::recursive_timed_mutex can be quite easily modeled with, for
example, semaphore.
Here it is:
class recursive_timed_mutex
{
public:
recursive_timed_mutex()
{
sema.init(false, 1, 1, $);
owner = -1;
recursion_count = 0;
}
~recursive_timed_mutex()
{
assert(owner == -1 && recursion_count == 0);
sema.deinit($);
}
void lock(rl::debug_info_param info)
{
rl::context& c = rl::ctx();
if (owner == c.current_thread())
{
RL_HIST(rl::user_msg_event) {"recursive mutex lock"}
RL_HIST_END();
assert(recursion_count > 0);
recursion_count += 1;
}
else
{
sema.wait(false, false, info);
assert(owner == -1 && recursion_count == 0);
owner = c.current_thread();
recursion_count = 1;
}
}
bool try_lock(rl::debug_info_param info)
{
rl::context& c = rl::ctx();
if (owner == c.current_thread())
{
RL_HIST(rl::user_msg_event) {"recursive mutex try lock"}
RL_HIST_END();
assert(recursion_count > 0);
recursion_count += 1;
return true;
}
else
{
rl::sema_wakeup_reason r = sema.wait(true, false, info);
if (r == rl::sema_wakeup_reason_success)
{
assert(owner == -1 && recursion_count == 0);
owner = c.current_thread();
recursion_count = 1;
return true;
}
else
{
return false;
}
}
}
void unlock(rl::debug_info_param info)
{
rl::context& c = rl::ctx();
assert(owner == c.current_thread() && recursion_count > 0);
RL_HIST(rl::user_msg_event) {"recursive mutex unlock"}
RL_HIST_END();
recursion_count -= 1;
if (recursion_count == 0)
{
owner = -1;
unsigned prev;
sema.post(1, prev, info);
}
}
bool timed_lock(rl::debug_info_param info, ... /*abs_time*/)
{
rl::context& c = rl::ctx();
if (owner == c.current_thread())
{
RL_HIST(rl::user_msg_event) {"recursive mutex timed lock"}
RL_HIST_END();
assert(recursion_count > 0);
recursion_count += 1;
return true;
}
else
{
rl::sema_wakeup_reason r = sema.wait(false, true, info);
if (r == rl::sema_wakeup_reason_success)
{
assert(owner == -1 && recursion_count == 0);
owner = c.current_thread();
recursion_count = 1;
return true;
}
else
{
return false;
}
}
}
private:
struct tag_t;
rl::semaphore<tag_t> sema;
rl::thread_id_t owner;
int recursion_count;
recursive_timed_mutex(recursive_timed_mutex const&);
recursive_timed_mutex& operator = (recursive_timed_mutex const&);
};
--
Dmitriy V'jukov