/usr/include/Wt/SyncLock is in libwt-dev 3.1.10-1ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | // This may look like C code, but it's really -*- C++ -*-
/*
* Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium.
*
* See the LICENSE file for terms of use.
*/
#ifndef WT_SYNC_LOCK_H_
#define WT_SYNC_LOCK_H_
#include <Wt/WGlobal>
#include <Wt/WApplication>
#include <boost/thread.hpp>
namespace Wt {
/*! \class SyncLock Wt/SyncLock Wt/SyncLock
* \brief An dead-lock avoidance adaptor for a Boost mutex lock.
*
* A %SyncLock adapts a Boost mutex lock (such as boost::mutex::scoped_lock),
* and provides the same API as the original lock (it derives from it).
*
* Just as can be expected by a lock, a call to lock() will block until the
* thread has exclusive access to the mutex.
*
* While waiting to acquire the lock, however, the current
* Wt::WApplication lock, may be temporarily released in favor of
* another helper thread trying to acquire the application lock. Thus,
* you need to be aware that when the lock is taken, some other thread
* may have modified the current application state.
*
* A sync lock is useful in the context of a deployment where multiple
* (or all) WApplication instances are running in a single process and
* communicating with each other (such as the built-in httpd). Then,
* this lock adaptor helps in avoiding a dead-lock situation when
* applications wants to access a shared resource protected by a
* mutex, which communicates to other applications while taking their
* update lock. In that case, it is likely that you will also want to
* iterate over all "registered" applications while holding the global
* mutex, and this creates a natural dead-lock scenario because you
* have two mutexes (global mutex, application mutex) which are
* sequentially aquired in a different order:
* - application mutex -> global mutex, during an application request
* - global mutex -> application mutex, while propagating events to applications
*
* The altered behaviour of a call by application <i>A</i> to lock()
* is that this application <i>A</i>'s state may be updated by another
* thread (e.g. serving application <i>B</i>), which tries to take
* <i>A</i>'s update lock.
*
* The following conventional locking code:
* \code
* boost::recursive_mutex::scoped_lock lock(mutex_);
* \endcode
* is updated to a sync lock, by doing:
* \code
* Wt::SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_);
* \endcode
*/
template <class Lock>
class SyncLock : public Lock
{
public:
/*! \brief Creates a RIIA lock.
*
* Initializes and acquires exclusive access to the \p mutex.
*/
template <class Mutex>
SyncLock(Mutex& mutex)
: Lock(mutex, boost::defer_lock)
{
lock();
}
/*! \brief Creates a RIIA lock, but defers taking the lock.
*
* Initialize the lock but defers taking the lock.
*
* \sa lock()
*/
template <class Mutex>
SyncLock(Mutex& mutex, boost::defer_lock_t)
: Lock(mutex, boost::defer_lock)
{ }
/*! \brief Tries to acquire the lock, blocking while waiting.
*
* While an application <i>A</i> is waiting for the lock, its state
* may be updated by another application: another application
* <i>B</i> can succesfully take <i>A's</i> \link
* WApplication::UpdateLock update lock\endlink.
*
* Therefore you need to be prepared to deal with application state
* changes while waiting for the lock.
*/
void lock() {
WApplication *app = WApplication::instance();
if (app) {
int id = app->startWaitingAtLock();
Lock::lock();
app->endWaitingAtLock(id);
} else
Lock::lock();
}
};
}
#endif // WT_SYNC_LOCK_H_
|