Merge pull request #21 from wilzbach/trailing-whitespace
Remove all trailing whitespace + add check
This commit is contained in:
commit
7f050af455
|
@ -1237,7 +1237,7 @@ package class VibedScheduler : Scheduler {
|
||||||
|
|
||||||
final switch (st_concurrencyPrimitive) with (ConcurrencyPrimitive) {
|
final switch (st_concurrencyPrimitive) with (ConcurrencyPrimitive) {
|
||||||
case task: runTask(op); break;
|
case task: runTask(op); break;
|
||||||
case workerTask:
|
case workerTask:
|
||||||
static void wrapper(shared(void delegate()) op) {
|
static void wrapper(shared(void delegate()) op) {
|
||||||
(cast(void delegate())op)();
|
(cast(void delegate())op)();
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ unittest {
|
||||||
|
|
||||||
struct LockedConnection(Connection) {
|
struct LockedConnection(Connection) {
|
||||||
import vibe.core.task : Task;
|
import vibe.core.task : Task;
|
||||||
|
|
||||||
private {
|
private {
|
||||||
ConnectionPool!Connection m_pool;
|
ConnectionPool!Connection m_pool;
|
||||||
Task m_task;
|
Task m_task;
|
||||||
|
|
|
@ -668,7 +668,7 @@ void yield()
|
||||||
to call `switchToTask` will result in task starvation and resource leakage.
|
to call `switchToTask` will result in task starvation and resource leakage.
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
on_interrupt = If specified, is required to
|
on_interrupt = If specified, is required to
|
||||||
|
|
||||||
See_Also: `switchToTask`
|
See_Also: `switchToTask`
|
||||||
*/
|
*/
|
||||||
|
@ -1064,7 +1064,7 @@ struct Timer {
|
||||||
|
|
||||||
/** Resets the timer to the specified timeout
|
/** Resets the timer to the specified timeout
|
||||||
*/
|
*/
|
||||||
void rearm(Duration dur, bool periodic = false) nothrow
|
void rearm(Duration dur, bool periodic = false) nothrow
|
||||||
in { assert(dur > 0.seconds, "Negative timer duration specified."); }
|
in { assert(dur > 0.seconds, "Negative timer duration specified."); }
|
||||||
body { m_driver.set(m_id, dur, periodic ? dur : 0.seconds); }
|
body { m_driver.set(m_id, dur, periodic ? dur : 0.seconds); }
|
||||||
|
|
||||||
|
|
|
@ -410,7 +410,7 @@ struct FileStream {
|
||||||
if (m_fd != FileFD.invalid)
|
if (m_fd != FileFD.invalid)
|
||||||
eventDriver.files.addRef(m_fd);
|
eventDriver.files.addRef(m_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
if (m_fd != FileFD.invalid)
|
if (m_fd != FileFD.invalid)
|
||||||
|
|
|
@ -252,7 +252,7 @@ final class FileLogger : Logger {
|
||||||
Format infoFormat = Format.thread;
|
Format infoFormat = Format.thread;
|
||||||
|
|
||||||
/** Use escape sequences to color log output.
|
/** Use escape sequences to color log output.
|
||||||
|
|
||||||
Note that the terminal must support 256-bit color codes.
|
Note that the terminal must support 256-bit color codes.
|
||||||
*/
|
*/
|
||||||
bool useColors = false;
|
bool useColors = false;
|
||||||
|
|
|
@ -391,7 +391,7 @@ struct GenericPath(F) {
|
||||||
|
|
||||||
/** Constructs a path from an input range of `Segment`s.
|
/** Constructs a path from an input range of `Segment`s.
|
||||||
|
|
||||||
Throws:
|
Throws:
|
||||||
Since path segments are pre-validated, this constructor does not
|
Since path segments are pre-validated, this constructor does not
|
||||||
throw an exception.
|
throw an exception.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -158,8 +158,8 @@ class LocalTaskSemaphore
|
||||||
LocalManualEvent m_signal;
|
LocalManualEvent m_signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(uint max_locks)
|
this(uint max_locks)
|
||||||
{
|
{
|
||||||
m_maxLocks = max_locks;
|
m_maxLocks = max_locks;
|
||||||
m_signal = createManualEvent();
|
m_signal = createManualEvent();
|
||||||
}
|
}
|
||||||
|
@ -182,10 +182,10 @@ class LocalTaskSemaphore
|
||||||
than one.
|
than one.
|
||||||
*/
|
*/
|
||||||
bool tryLock()
|
bool tryLock()
|
||||||
{
|
{
|
||||||
if (available > 0)
|
if (available > 0)
|
||||||
{
|
{
|
||||||
m_locks++;
|
m_locks++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -202,13 +202,13 @@ class LocalTaskSemaphore
|
||||||
|
|
||||||
if (tryLock())
|
if (tryLock())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ThreadWaiter w;
|
ThreadWaiter w;
|
||||||
w.priority = priority;
|
w.priority = priority;
|
||||||
w.seq = min(0, m_seq - w.priority);
|
w.seq = min(0, m_seq - w.priority);
|
||||||
if (++m_seq == uint.max)
|
if (++m_seq == uint.max)
|
||||||
rewindSeq();
|
rewindSeq();
|
||||||
|
|
||||||
() @trusted { m_waiters.insert(w); } ();
|
() @trusted { m_waiters.insert(w); } ();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -222,7 +222,7 @@ class LocalTaskSemaphore
|
||||||
|
|
||||||
/** Gives up an existing lock.
|
/** Gives up an existing lock.
|
||||||
*/
|
*/
|
||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
assert(m_locks >= 1);
|
assert(m_locks >= 1);
|
||||||
m_locks--;
|
m_locks--;
|
||||||
|
@ -232,7 +232,7 @@ class LocalTaskSemaphore
|
||||||
|
|
||||||
// if true, a goes after b. ie. b comes out front()
|
// if true, a goes after b. ie. b comes out front()
|
||||||
/// private
|
/// private
|
||||||
static bool asc(ref ThreadWaiter a, ref ThreadWaiter b)
|
static bool asc(ref ThreadWaiter a, ref ThreadWaiter b)
|
||||||
{
|
{
|
||||||
if (a.priority != b.priority)
|
if (a.priority != b.priority)
|
||||||
return a.priority < b.priority;
|
return a.priority < b.priority;
|
||||||
|
@ -735,7 +735,7 @@ struct LocalManualEvent {
|
||||||
int wait(int emit_count) { return doWait!true(Duration.max, emit_count); }
|
int wait(int emit_count) { return doWait!true(Duration.max, emit_count); }
|
||||||
/// ditto
|
/// ditto
|
||||||
int wait(Duration timeout, int emit_count) { return doWait!true(timeout, emit_count); }
|
int wait(Duration timeout, int emit_count) { return doWait!true(timeout, emit_count); }
|
||||||
|
|
||||||
/** Same as $(D wait), but defers throwing any $(D InterruptException).
|
/** Same as $(D wait), but defers throwing any $(D InterruptException).
|
||||||
|
|
||||||
This method is annotated $(D nothrow) at the expense that it cannot be
|
This method is annotated $(D nothrow) at the expense that it cannot be
|
||||||
|
@ -905,7 +905,7 @@ struct ManualEvent {
|
||||||
int wait(int emit_count) shared { return doWaitShared!true(Duration.max, emit_count); }
|
int wait(int emit_count) shared { return doWaitShared!true(Duration.max, emit_count); }
|
||||||
/// ditto
|
/// ditto
|
||||||
int wait(Duration timeout, int emit_count) shared { return doWaitShared!true(timeout, emit_count); }
|
int wait(Duration timeout, int emit_count) shared { return doWaitShared!true(timeout, emit_count); }
|
||||||
|
|
||||||
/** Same as $(D wait), but defers throwing any $(D InterruptException).
|
/** Same as $(D wait), but defers throwing any $(D InterruptException).
|
||||||
|
|
||||||
This method is annotated $(D nothrow) at the expense that it cannot be
|
This method is annotated $(D nothrow) at the expense that it cannot be
|
||||||
|
@ -1249,7 +1249,7 @@ private struct ThreadLocalWaiter {
|
||||||
} else {
|
} else {
|
||||||
asyncAwaitAny!interruptible(timeout, waitable);
|
asyncAwaitAny!interruptible(timeout, waitable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (waitable.cancelled) {
|
if (waitable.cancelled) {
|
||||||
removeWaiter();
|
removeWaiter();
|
||||||
return false;
|
return false;
|
||||||
|
@ -1548,7 +1548,7 @@ private struct TaskConditionImpl(bool INTERRUPTIBLE, LOCKABLE) {
|
||||||
* the actual functionality of their method calls.
|
* the actual functionality of their method calls.
|
||||||
*
|
*
|
||||||
* The method implementations are based on two static parameters
|
* The method implementations are based on two static parameters
|
||||||
* ($(D INTERRUPTIBLE) and $(D INTENT)), which are configured through
|
* ($(D INTERRUPTIBLE) and $(D INTENT)), which are configured through
|
||||||
* template arguments:
|
* template arguments:
|
||||||
*
|
*
|
||||||
* - $(D INTERRUPTIBLE) determines whether the mutex implementation
|
* - $(D INTERRUPTIBLE) determines whether the mutex implementation
|
||||||
|
@ -1565,12 +1565,12 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
{
|
{
|
||||||
/** The policy with which the mutex should operate.
|
/** The policy with which the mutex should operate.
|
||||||
*
|
*
|
||||||
* The policy determines how the acquisition of the locks is
|
* The policy determines how the acquisition of the locks is
|
||||||
* performed and can be used to tune the mutex according to the
|
* performed and can be used to tune the mutex according to the
|
||||||
* underlying algorithm in which it is used.
|
* underlying algorithm in which it is used.
|
||||||
*
|
*
|
||||||
* According to the provided policy, the mutex will either favor
|
* According to the provided policy, the mutex will either favor
|
||||||
* reading or writing tasks and could potentially starve the
|
* reading or writing tasks and could potentially starve the
|
||||||
* respective opposite.
|
* respective opposite.
|
||||||
*
|
*
|
||||||
* cf. $(D core.sync.rwmutex.ReadWriteMutex.Policy)
|
* cf. $(D core.sync.rwmutex.ReadWriteMutex.Policy)
|
||||||
|
@ -1582,7 +1582,7 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
/** Writers are prioritized, readers may be starved as a result. */
|
/** Writers are prioritized, readers may be starved as a result. */
|
||||||
PREFER_WRITERS
|
PREFER_WRITERS
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The intent with which a locking operation is performed.
|
/** The intent with which a locking operation is performed.
|
||||||
*
|
*
|
||||||
* Since both locks share the same underlying algorithms, the actual
|
* Since both locks share the same underlying algorithms, the actual
|
||||||
|
@ -1598,23 +1598,23 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
* hold a lock at any given time. */
|
* hold a lock at any given time. */
|
||||||
READ_WRITE = 1
|
READ_WRITE = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
private {
|
private {
|
||||||
//Queue counters
|
//Queue counters
|
||||||
/** The number of reading tasks waiting for the lock to become available. */
|
/** The number of reading tasks waiting for the lock to become available. */
|
||||||
shared(uint) m_waitingForReadLock = 0;
|
shared(uint) m_waitingForReadLock = 0;
|
||||||
/** The number of writing tasks waiting for the lock to become available. */
|
/** The number of writing tasks waiting for the lock to become available. */
|
||||||
shared(uint) m_waitingForWriteLock = 0;
|
shared(uint) m_waitingForWriteLock = 0;
|
||||||
|
|
||||||
//Lock counters
|
//Lock counters
|
||||||
/** The number of reading tasks that currently hold the lock. */
|
/** The number of reading tasks that currently hold the lock. */
|
||||||
uint m_activeReadLocks = 0;
|
uint m_activeReadLocks = 0;
|
||||||
/** The number of writing tasks that currently hold the lock (binary). */
|
/** The number of writing tasks that currently hold the lock (binary). */
|
||||||
ubyte m_activeWriteLocks = 0;
|
ubyte m_activeWriteLocks = 0;
|
||||||
|
|
||||||
/** The policy determining the lock's behavior. */
|
/** The policy determining the lock's behavior. */
|
||||||
Policy m_policy;
|
Policy m_policy;
|
||||||
|
|
||||||
//Queue Events
|
//Queue Events
|
||||||
/** The event used to wake reading tasks waiting for the lock while it is blocked. */
|
/** The event used to wake reading tasks waiting for the lock while it is blocked. */
|
||||||
shared(ManualEvent) m_readyForReadLock;
|
shared(ManualEvent) m_readyForReadLock;
|
||||||
|
@ -1624,7 +1624,7 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
/** The underlying mutex that gates the access to the shared state. */
|
/** The underlying mutex that gates the access to the shared state. */
|
||||||
Mutex m_counterMutex;
|
Mutex m_counterMutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(Policy policy)
|
this(Policy policy)
|
||||||
{
|
{
|
||||||
m_policy = policy;
|
m_policy = policy;
|
||||||
|
@ -1634,10 +1634,10 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@disable this(this);
|
@disable this(this);
|
||||||
|
|
||||||
/** The policy with which the lock has been created. */
|
/** The policy with which the lock has been created. */
|
||||||
@property policy() const { return m_policy; }
|
@property policy() const { return m_policy; }
|
||||||
|
|
||||||
version(RWMutexPrint)
|
version(RWMutexPrint)
|
||||||
{
|
{
|
||||||
/** Print out debug information during lock operations. */
|
/** Print out debug information during lock operations. */
|
||||||
|
@ -1647,17 +1647,17 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
writefln("RWMutex: %s (%s), active: RO: %d, RW: %d; waiting: RO: %d, RW: %d",
|
writefln("RWMutex: %s (%s), active: RO: %d, RW: %d; waiting: RO: %d, RW: %d",
|
||||||
OP.leftJustify(10,' '),
|
OP.leftJustify(10,' '),
|
||||||
INTENT == LockingIntent.READ_ONLY ? "RO" : "RW",
|
INTENT == LockingIntent.READ_ONLY ? "RO" : "RW",
|
||||||
m_activeReadLocks, m_activeWriteLocks,
|
m_activeReadLocks, m_activeWriteLocks,
|
||||||
m_waitingForReadLock, m_waitingForWriteLock
|
m_waitingForReadLock, m_waitingForWriteLock
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (Throwable t){}
|
catch (Throwable t){}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An internal shortcut method to determine the queue event for a given intent. */
|
/** An internal shortcut method to determine the queue event for a given intent. */
|
||||||
@property ref auto queueEvent(LockingIntent INTENT)()
|
@property ref auto queueEvent(LockingIntent INTENT)()
|
||||||
{
|
{
|
||||||
|
@ -1666,7 +1666,7 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
else
|
else
|
||||||
return m_readyForWriteLock;
|
return m_readyForWriteLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An internal shortcut method to determine the queue counter for a given intent. */
|
/** An internal shortcut method to determine the queue counter for a given intent. */
|
||||||
@property ref auto queueCounter(LockingIntent INTENT)()
|
@property ref auto queueCounter(LockingIntent INTENT)()
|
||||||
{
|
{
|
||||||
|
@ -1675,13 +1675,13 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
else
|
else
|
||||||
return m_waitingForWriteLock;
|
return m_waitingForWriteLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An internal shortcut method to determine the current emitCount of the queue counter for a given intent. */
|
/** An internal shortcut method to determine the current emitCount of the queue counter for a given intent. */
|
||||||
int emitCount(LockingIntent INTENT)()
|
int emitCount(LockingIntent INTENT)()
|
||||||
{
|
{
|
||||||
return queueEvent!INTENT.emitCount();
|
return queueEvent!INTENT.emitCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An internal shortcut method to determine the active counter for a given intent. */
|
/** An internal shortcut method to determine the active counter for a given intent. */
|
||||||
@property ref auto activeCounter(LockingIntent INTENT)()
|
@property ref auto activeCounter(LockingIntent INTENT)()
|
||||||
{
|
{
|
||||||
|
@ -1690,8 +1690,8 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
else
|
else
|
||||||
return m_activeWriteLocks;
|
return m_activeWriteLocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An internal shortcut method to wait for the queue event for a given intent.
|
/** An internal shortcut method to wait for the queue event for a given intent.
|
||||||
*
|
*
|
||||||
* This method is used during the `lock()` operation, after a
|
* This method is used during the `lock()` operation, after a
|
||||||
* `tryLock()` operation has been unsuccessfully finished.
|
* `tryLock()` operation has been unsuccessfully finished.
|
||||||
|
@ -1705,8 +1705,8 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
else
|
else
|
||||||
return queueEvent!INTENT.waitUninterruptible(count);
|
return queueEvent!INTENT.waitUninterruptible(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An internal shortcut method to notify tasks waiting for the lock to become available again.
|
/** An internal shortcut method to notify tasks waiting for the lock to become available again.
|
||||||
*
|
*
|
||||||
* This method is called whenever the number of owners of the mutex hits
|
* This method is called whenever the number of owners of the mutex hits
|
||||||
* zero; this is basically the counterpart to `wait()`.
|
* zero; this is basically the counterpart to `wait()`.
|
||||||
|
@ -1723,12 +1723,12 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
{ //If a writer unlocks the mutex, notify both readers and writers
|
{ //If a writer unlocks the mutex, notify both readers and writers
|
||||||
if (atomicLoad(m_waitingForReadLock) > 0)
|
if (atomicLoad(m_waitingForReadLock) > 0)
|
||||||
m_readyForReadLock.emit();
|
m_readyForReadLock.emit();
|
||||||
|
|
||||||
if (atomicLoad(m_waitingForWriteLock) > 0)
|
if (atomicLoad(m_waitingForWriteLock) > 0)
|
||||||
m_readyForWriteLock.emit();
|
m_readyForWriteLock.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An internal method that performs the acquisition attempt in different variations.
|
/** An internal method that performs the acquisition attempt in different variations.
|
||||||
*
|
*
|
||||||
* Since both locks rely on a common TaskMutex object which gates the access
|
* Since both locks rely on a common TaskMutex object which gates the access
|
||||||
|
@ -1736,15 +1736,15 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
* than for simple mutex variants. This method will thus be performing the
|
* than for simple mutex variants. This method will thus be performing the
|
||||||
* `tryLock()` operation in two variations, depending on the callee:
|
* `tryLock()` operation in two variations, depending on the callee:
|
||||||
*
|
*
|
||||||
* If called from the outside ($(D WAIT_FOR_BLOCKING_MUTEX) = false), the method
|
* If called from the outside ($(D WAIT_FOR_BLOCKING_MUTEX) = false), the method
|
||||||
* will instantly fail if the underlying mutex is locked (i.e. during another
|
* will instantly fail if the underlying mutex is locked (i.e. during another
|
||||||
* `tryLock()` or `unlock()` operation), in order to guarantee the fastest
|
* `tryLock()` or `unlock()` operation), in order to guarantee the fastest
|
||||||
* possible locking attempt.
|
* possible locking attempt.
|
||||||
*
|
*
|
||||||
* If used internally by the `lock()` method ($(D WAIT_FOR_BLOCKING_MUTEX) = true),
|
* If used internally by the `lock()` method ($(D WAIT_FOR_BLOCKING_MUTEX) = true),
|
||||||
* the operation will wait for the mutex to be available before deciding if
|
* the operation will wait for the mutex to be available before deciding if
|
||||||
* the lock can be acquired, since the attempt would anyway be repeated until
|
* the lock can be acquired, since the attempt would anyway be repeated until
|
||||||
* it succeeds. This will prevent frequent retries under heavy loads and thus
|
* it succeeds. This will prevent frequent retries under heavy loads and thus
|
||||||
* should ensure better performance.
|
* should ensure better performance.
|
||||||
*/
|
*/
|
||||||
@trusted bool tryLock(LockingIntent INTENT, bool WAIT_FOR_BLOCKING_MUTEX)()
|
@trusted bool tryLock(LockingIntent INTENT, bool WAIT_FOR_BLOCKING_MUTEX)()
|
||||||
|
@ -1752,7 +1752,7 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
//Log a debug statement for the attempt
|
//Log a debug statement for the attempt
|
||||||
version(RWMutexPrint)
|
version(RWMutexPrint)
|
||||||
printInfo!("tryLock",INTENT)();
|
printInfo!("tryLock",INTENT)();
|
||||||
|
|
||||||
//Try to acquire the lock
|
//Try to acquire the lock
|
||||||
static if (!WAIT_FOR_BLOCKING_MUTEX)
|
static if (!WAIT_FOR_BLOCKING_MUTEX)
|
||||||
{
|
{
|
||||||
|
@ -1761,43 +1761,43 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_counterMutex.lock();
|
m_counterMutex.lock();
|
||||||
|
|
||||||
scope(exit)
|
scope(exit)
|
||||||
m_counterMutex.unlock();
|
m_counterMutex.unlock();
|
||||||
|
|
||||||
//Log a debug statement for the attempt
|
//Log a debug statement for the attempt
|
||||||
version(RWMutexPrint)
|
version(RWMutexPrint)
|
||||||
printInfo!("checkCtrs",INTENT)();
|
printInfo!("checkCtrs",INTENT)();
|
||||||
|
|
||||||
//Check if there's already an active writer
|
//Check if there's already an active writer
|
||||||
if (m_activeWriteLocks > 0)
|
if (m_activeWriteLocks > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//If writers are preferred over readers, check whether there
|
//If writers are preferred over readers, check whether there
|
||||||
//currently is a writer in the waiting queue and abort if
|
//currently is a writer in the waiting queue and abort if
|
||||||
//that's the case.
|
//that's the case.
|
||||||
static if (INTENT == LockingIntent.READ_ONLY)
|
static if (INTENT == LockingIntent.READ_ONLY)
|
||||||
if (m_policy.PREFER_WRITERS && m_waitingForWriteLock > 0)
|
if (m_policy.PREFER_WRITERS && m_waitingForWriteLock > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//If we are locking the mutex for writing, make sure that
|
//If we are locking the mutex for writing, make sure that
|
||||||
//there's no reader active.
|
//there's no reader active.
|
||||||
static if (INTENT == LockingIntent.READ_WRITE)
|
static if (INTENT == LockingIntent.READ_WRITE)
|
||||||
if (m_activeReadLocks > 0)
|
if (m_activeReadLocks > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//We can successfully acquire the lock!
|
//We can successfully acquire the lock!
|
||||||
//Log a debug statement for the success.
|
//Log a debug statement for the success.
|
||||||
version(RWMutexPrint)
|
version(RWMutexPrint)
|
||||||
printInfo!("lock",INTENT)();
|
printInfo!("lock",INTENT)();
|
||||||
|
|
||||||
//Increase the according counter
|
//Increase the according counter
|
||||||
//(number of active readers/writers)
|
//(number of active readers/writers)
|
||||||
//and return a success code.
|
//and return a success code.
|
||||||
activeCounter!INTENT += 1;
|
activeCounter!INTENT += 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attempt to acquire the lock for a given intent.
|
/** Attempt to acquire the lock for a given intent.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
|
@ -1810,7 +1810,7 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
//TaskMutex - fail if it is already blocked.
|
//TaskMutex - fail if it is already blocked.
|
||||||
return tryLock!(INTENT,false)();
|
return tryLock!(INTENT,false)();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Acquire the lock for the given intent; yield and suspend until the lock has been acquired. */
|
/** Acquire the lock for the given intent; yield and suspend until the lock has been acquired. */
|
||||||
@trusted void lock(LockingIntent INTENT)()
|
@trusted void lock(LockingIntent INTENT)()
|
||||||
{
|
{
|
||||||
|
@ -1822,29 +1822,29 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
atomicOp!"+="(queueCounter!INTENT,1);
|
atomicOp!"+="(queueCounter!INTENT,1);
|
||||||
scope(exit)
|
scope(exit)
|
||||||
atomicOp!"-="(queueCounter!INTENT,1);
|
atomicOp!"-="(queueCounter!INTENT,1);
|
||||||
|
|
||||||
//Try to lock the mutex
|
//Try to lock the mutex
|
||||||
auto locked = tryLock!(INTENT,true)();
|
auto locked = tryLock!(INTENT,true)();
|
||||||
if (locked)
|
if (locked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Retry until we successfully acquired the lock
|
//Retry until we successfully acquired the lock
|
||||||
while(!locked)
|
while(!locked)
|
||||||
{
|
{
|
||||||
version(RWMutexPrint)
|
version(RWMutexPrint)
|
||||||
printInfo!("wait",INTENT)();
|
printInfo!("wait",INTENT)();
|
||||||
|
|
||||||
count = wait!INTENT(count);
|
count = wait!INTENT(count);
|
||||||
locked = tryLock!(INTENT,true)();
|
locked = tryLock!(INTENT,true)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unlock the mutex after a successful acquisition. */
|
/** Unlock the mutex after a successful acquisition. */
|
||||||
@trusted void unlock(LockingIntent INTENT)()
|
@trusted void unlock(LockingIntent INTENT)()
|
||||||
{
|
{
|
||||||
version(RWMutexPrint)
|
version(RWMutexPrint)
|
||||||
printInfo!("unlock",INTENT)();
|
printInfo!("unlock",INTENT)();
|
||||||
|
|
||||||
debug assert(activeCounter!INTENT > 0);
|
debug assert(activeCounter!INTENT > 0);
|
||||||
|
|
||||||
synchronized(m_counterMutex)
|
synchronized(m_counterMutex)
|
||||||
|
@ -1856,7 +1856,7 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
{
|
{
|
||||||
version(RWMutexPrint)
|
version(RWMutexPrint)
|
||||||
printInfo!("notify",INTENT)();
|
printInfo!("notify",INTENT)();
|
||||||
|
|
||||||
notify!INTENT();
|
notify!INTENT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1867,20 +1867,20 @@ private struct ReadWriteMutexState(bool INTERRUPTIBLE)
|
||||||
*
|
*
|
||||||
* This mutex can be used in exchange for a $(D core.sync.mutex.ReadWriteMutex),
|
* This mutex can be used in exchange for a $(D core.sync.mutex.ReadWriteMutex),
|
||||||
* but does not block the event loop in contention situations. The `reader` and `writer`
|
* but does not block the event loop in contention situations. The `reader` and `writer`
|
||||||
* members are used for locking. Locking the `reader` mutex allows access to multiple
|
* members are used for locking. Locking the `reader` mutex allows access to multiple
|
||||||
* readers at once, while the `writer` mutex only allows a single writer to lock it at
|
* readers at once, while the `writer` mutex only allows a single writer to lock it at
|
||||||
* any given time. Locks on `reader` and `writer` are mutually exclusive (i.e. whenever a
|
* any given time. Locks on `reader` and `writer` are mutually exclusive (i.e. whenever a
|
||||||
* writer is active, no readers can be active at the same time, and vice versa).
|
* writer is active, no readers can be active at the same time, and vice versa).
|
||||||
*
|
*
|
||||||
* Notice:
|
* Notice:
|
||||||
* Mutexes implemented by this class cannot be interrupted
|
* Mutexes implemented by this class cannot be interrupted
|
||||||
* using $(D vibe.core.task.Task.interrupt()). The corresponding
|
* using $(D vibe.core.task.Task.interrupt()). The corresponding
|
||||||
* InterruptException will be deferred until the next blocking
|
* InterruptException will be deferred until the next blocking
|
||||||
* operation yields the event loop.
|
* operation yields the event loop.
|
||||||
*
|
*
|
||||||
* Use $(D InterruptibleTaskReadWriteMutex) as an alternative that can be
|
* Use $(D InterruptibleTaskReadWriteMutex) as an alternative that can be
|
||||||
* interrupted.
|
* interrupted.
|
||||||
*
|
*
|
||||||
* cf. $(D core.sync.mutex.ReadWriteMutex)
|
* cf. $(D core.sync.mutex.ReadWriteMutex)
|
||||||
*/
|
*/
|
||||||
class TaskReadWriteMutex
|
class TaskReadWriteMutex
|
||||||
|
@ -1890,29 +1890,29 @@ class TaskReadWriteMutex
|
||||||
alias LockingIntent = State.LockingIntent;
|
alias LockingIntent = State.LockingIntent;
|
||||||
alias READ_ONLY = LockingIntent.READ_ONLY;
|
alias READ_ONLY = LockingIntent.READ_ONLY;
|
||||||
alias READ_WRITE = LockingIntent.READ_WRITE;
|
alias READ_WRITE = LockingIntent.READ_WRITE;
|
||||||
|
|
||||||
/** The shared state used by the reader and writer mutexes. */
|
/** The shared state used by the reader and writer mutexes. */
|
||||||
State m_state;
|
State m_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The policy with which the mutex should operate.
|
/** The policy with which the mutex should operate.
|
||||||
*
|
*
|
||||||
* The policy determines how the acquisition of the locks is
|
* The policy determines how the acquisition of the locks is
|
||||||
* performed and can be used to tune the mutex according to the
|
* performed and can be used to tune the mutex according to the
|
||||||
* underlying algorithm in which it is used.
|
* underlying algorithm in which it is used.
|
||||||
*
|
*
|
||||||
* According to the provided policy, the mutex will either favor
|
* According to the provided policy, the mutex will either favor
|
||||||
* reading or writing tasks and could potentially starve the
|
* reading or writing tasks and could potentially starve the
|
||||||
* respective opposite.
|
* respective opposite.
|
||||||
*
|
*
|
||||||
* cf. $(D core.sync.rwmutex.ReadWriteMutex.Policy)
|
* cf. $(D core.sync.rwmutex.ReadWriteMutex.Policy)
|
||||||
*/
|
*/
|
||||||
alias Policy = State.Policy;
|
alias Policy = State.Policy;
|
||||||
|
|
||||||
/** A common baseclass for both of the provided mutexes.
|
/** A common baseclass for both of the provided mutexes.
|
||||||
*
|
*
|
||||||
* The intent for the according mutex is specified through the
|
* The intent for the according mutex is specified through the
|
||||||
* $(D INTENT) template argument, which determines if a mutex is
|
* $(D INTENT) template argument, which determines if a mutex is
|
||||||
* used for read or write locking.
|
* used for read or write locking.
|
||||||
*/
|
*/
|
||||||
final class Mutex(LockingIntent INTENT): core.sync.mutex.Mutex, Lockable
|
final class Mutex(LockingIntent INTENT): core.sync.mutex.Mutex, Lockable
|
||||||
|
@ -1926,17 +1926,17 @@ class TaskReadWriteMutex
|
||||||
}
|
}
|
||||||
alias Reader = Mutex!READ_ONLY;
|
alias Reader = Mutex!READ_ONLY;
|
||||||
alias Writer = Mutex!READ_WRITE;
|
alias Writer = Mutex!READ_WRITE;
|
||||||
|
|
||||||
Reader reader;
|
Reader reader;
|
||||||
Writer writer;
|
Writer writer;
|
||||||
|
|
||||||
this(Policy policy = Policy.PREFER_WRITERS)
|
this(Policy policy = Policy.PREFER_WRITERS)
|
||||||
{
|
{
|
||||||
m_state = State(policy);
|
m_state = State(policy);
|
||||||
reader = new Reader();
|
reader = new Reader();
|
||||||
writer = new Writer();
|
writer = new Writer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The policy with which the lock has been created. */
|
/** The policy with which the lock has been created. */
|
||||||
@property Policy policy() const { return m_state.policy; }
|
@property Policy policy() const { return m_state.policy; }
|
||||||
}
|
}
|
||||||
|
@ -1945,7 +1945,7 @@ class TaskReadWriteMutex
|
||||||
*
|
*
|
||||||
* This class supports the use of $(D vibe.core.task.Task.interrupt()) while
|
* This class supports the use of $(D vibe.core.task.Task.interrupt()) while
|
||||||
* waiting in the `lock()` method.
|
* waiting in the `lock()` method.
|
||||||
*
|
*
|
||||||
* cf. $(D core.sync.mutex.ReadWriteMutex)
|
* cf. $(D core.sync.mutex.ReadWriteMutex)
|
||||||
*/
|
*/
|
||||||
class InterruptibleTaskReadWriteMutex
|
class InterruptibleTaskReadWriteMutex
|
||||||
|
@ -1957,31 +1957,31 @@ class InterruptibleTaskReadWriteMutex
|
||||||
alias LockingIntent = State.LockingIntent;
|
alias LockingIntent = State.LockingIntent;
|
||||||
alias READ_ONLY = LockingIntent.READ_ONLY;
|
alias READ_ONLY = LockingIntent.READ_ONLY;
|
||||||
alias READ_WRITE = LockingIntent.READ_WRITE;
|
alias READ_WRITE = LockingIntent.READ_WRITE;
|
||||||
|
|
||||||
/** The shared state used by the reader and writer mutexes. */
|
/** The shared state used by the reader and writer mutexes. */
|
||||||
State m_state;
|
State m_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The policy with which the mutex should operate.
|
/** The policy with which the mutex should operate.
|
||||||
*
|
*
|
||||||
* The policy determines how the acquisition of the locks is
|
* The policy determines how the acquisition of the locks is
|
||||||
* performed and can be used to tune the mutex according to the
|
* performed and can be used to tune the mutex according to the
|
||||||
* underlying algorithm in which it is used.
|
* underlying algorithm in which it is used.
|
||||||
*
|
*
|
||||||
* According to the provided policy, the mutex will either favor
|
* According to the provided policy, the mutex will either favor
|
||||||
* reading or writing tasks and could potentially starve the
|
* reading or writing tasks and could potentially starve the
|
||||||
* respective opposite.
|
* respective opposite.
|
||||||
*
|
*
|
||||||
* cf. $(D core.sync.rwmutex.ReadWriteMutex.Policy)
|
* cf. $(D core.sync.rwmutex.ReadWriteMutex.Policy)
|
||||||
*/
|
*/
|
||||||
alias Policy = State.Policy;
|
alias Policy = State.Policy;
|
||||||
|
|
||||||
/** A common baseclass for both of the provided mutexes.
|
/** A common baseclass for both of the provided mutexes.
|
||||||
*
|
*
|
||||||
* The intent for the according mutex is specified through the
|
* The intent for the according mutex is specified through the
|
||||||
* $(D INTENT) template argument, which determines if a mutex is
|
* $(D INTENT) template argument, which determines if a mutex is
|
||||||
* used for read or write locking.
|
* used for read or write locking.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
final class Mutex(LockingIntent INTENT): core.sync.mutex.Mutex, Lockable
|
final class Mutex(LockingIntent INTENT): core.sync.mutex.Mutex, Lockable
|
||||||
{
|
{
|
||||||
|
@ -1994,17 +1994,17 @@ class InterruptibleTaskReadWriteMutex
|
||||||
}
|
}
|
||||||
alias Reader = Mutex!READ_ONLY;
|
alias Reader = Mutex!READ_ONLY;
|
||||||
alias Writer = Mutex!READ_WRITE;
|
alias Writer = Mutex!READ_WRITE;
|
||||||
|
|
||||||
Reader reader;
|
Reader reader;
|
||||||
Writer writer;
|
Writer writer;
|
||||||
|
|
||||||
this(Policy policy = Policy.PREFER_WRITERS)
|
this(Policy policy = Policy.PREFER_WRITERS)
|
||||||
{
|
{
|
||||||
m_state = State(policy);
|
m_state = State(policy);
|
||||||
reader = new Reader();
|
reader = new Reader();
|
||||||
writer = new Writer();
|
writer = new Writer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The policy with which the lock has been created. */
|
/** The policy with which the lock has been created. */
|
||||||
@property Policy policy() const { return m_state.policy; }
|
@property Policy policy() const { return m_state.policy; }
|
||||||
}
|
}
|
|
@ -77,7 +77,7 @@ struct Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
package @property ref ThreadInfo tidInfo() @system { return m_fiber ? taskFiber.tidInfo : s_tidInfo; } // FIXME: this is not thread safe!
|
package @property ref ThreadInfo tidInfo() @system { return m_fiber ? taskFiber.tidInfo : s_tidInfo; } // FIXME: this is not thread safe!
|
||||||
|
|
||||||
@property Tid tid() @trusted { return tidInfo.ident; }
|
@property Tid tid() @trusted { return tidInfo.ident; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +346,7 @@ final package class TaskFiber : Fiber {
|
||||||
import std.concurrency : Tid, thisTid;
|
import std.concurrency : Tid, thisTid;
|
||||||
import std.encoding : sanitize;
|
import std.encoding : sanitize;
|
||||||
import vibe.core.core : isEventLoopRunning, recycleFiber, taskScheduler, yield;
|
import vibe.core.core : isEventLoopRunning, recycleFiber, taskScheduler, yield;
|
||||||
|
|
||||||
version (VibeDebugCatchAll) alias UncaughtException = Throwable;
|
version (VibeDebugCatchAll) alias UncaughtException = Throwable;
|
||||||
else alias UncaughtException = Exception;
|
else alias UncaughtException = Exception;
|
||||||
try {
|
try {
|
||||||
|
@ -521,7 +521,7 @@ package struct TaskFuncInfo {
|
||||||
|
|
||||||
import std.algorithm : move;
|
import std.algorithm : move;
|
||||||
import std.traits : hasElaborateAssign;
|
import std.traits : hasElaborateAssign;
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
|
|
||||||
static struct TARGS { ARGS expand; }
|
static struct TARGS { ARGS expand; }
|
||||||
|
|
||||||
|
@ -745,7 +745,7 @@ package struct TaskScheduler {
|
||||||
|
|
||||||
/** Holds execution until the task gets explicitly resumed.
|
/** Holds execution until the task gets explicitly resumed.
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void hibernate()
|
void hibernate()
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@ shared class TaskPool {
|
||||||
threads.length = thread_count;
|
threads.length = thread_count;
|
||||||
foreach (i; 0 .. thread_count) {
|
foreach (i; 0 .. thread_count) {
|
||||||
WorkerThread thr;
|
WorkerThread thr;
|
||||||
() @trusted {
|
() @trusted {
|
||||||
thr = new WorkerThread(this);
|
thr = new WorkerThread(this);
|
||||||
thr.name = format("vibe-%s", i);
|
thr.name = format("vibe-%s", i);
|
||||||
thr.start();
|
thr.start();
|
||||||
|
@ -338,7 +338,7 @@ nothrow @safe:
|
||||||
bool consume(ref TaskFuncInfo tfi)
|
bool consume(ref TaskFuncInfo tfi)
|
||||||
{
|
{
|
||||||
import std.algorithm.mutation : swap;
|
import std.algorithm.mutation : swap;
|
||||||
|
|
||||||
if (m_queue.empty) return false;
|
if (m_queue.empty) return false;
|
||||||
swap(tfi, m_queue.front);
|
swap(tfi, m_queue.front);
|
||||||
m_queue.popFront();
|
m_queue.popFront();
|
||||||
|
|
|
@ -61,7 +61,7 @@ struct Waitable(CB, alias wait, alias cancel, on_result...)
|
||||||
|
|
||||||
bool cancelled;
|
bool cancelled;
|
||||||
auto waitCallback(Callback cb) nothrow { return wait(cb); }
|
auto waitCallback(Callback cb) nothrow { return wait(cb); }
|
||||||
|
|
||||||
static if (is(ReturnType!waitCallback == void))
|
static if (is(ReturnType!waitCallback == void))
|
||||||
void cancelCallback(Callback cb) nothrow { cancel(cb); }
|
void cancelCallback(Callback cb) nothrow { cancel(cb); }
|
||||||
else
|
else
|
||||||
|
|
|
@ -440,7 +440,7 @@ template checkInterfaceConformance(T, I) {
|
||||||
}
|
}
|
||||||
alias checkMemberConformance = impl!0;
|
alias checkMemberConformance = impl!0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template impl(size_t i) {
|
template impl(size_t i) {
|
||||||
static if (i < Members.length) {
|
static if (i < Members.length) {
|
||||||
static if (__traits(compiles, __traits(getMember, I, Members[i])))
|
static if (__traits(compiles, __traits(getMember, I, Members[i])))
|
||||||
|
|
|
@ -70,13 +70,13 @@ void runTest()
|
||||||
remove(bar);
|
remove(bar);
|
||||||
watcher = Path(dir).watchDirectory(Yes.recursive);
|
watcher = Path(dir).watchDirectory(Yes.recursive);
|
||||||
write(foo, null);
|
write(foo, null);
|
||||||
sleep(1.seconds);
|
sleep(1.seconds);
|
||||||
write(foo, [0, 1]);
|
write(foo, [0, 1]);
|
||||||
sleep(100.msecs);
|
sleep(100.msecs);
|
||||||
remove(foo);
|
remove(foo);
|
||||||
|
|
||||||
write(bar, null);
|
write(bar, null);
|
||||||
sleep(1.seconds);
|
sleep(1.seconds);
|
||||||
write(bar, [0, 1]);
|
write(bar, [0, 1]);
|
||||||
sleep(100.msecs);
|
sleep(100.msecs);
|
||||||
remove(bar);
|
remove(bar);
|
||||||
|
|
|
@ -20,7 +20,7 @@ void test()
|
||||||
assert(gotit);
|
assert(gotit);
|
||||||
sleep(10.msecs);
|
sleep(10.msecs);
|
||||||
});
|
});
|
||||||
|
|
||||||
t.tid.send(10);
|
t.tid.send(10);
|
||||||
t.tid.send(11); // never received
|
t.tid.send(11); // never received
|
||||||
t.join();
|
t.join();
|
||||||
|
@ -43,9 +43,9 @@ void test()
|
||||||
|
|
||||||
t3.tid.send(13);
|
t3.tid.send(13);
|
||||||
sleep(10.msecs);
|
sleep(10.msecs);
|
||||||
|
|
||||||
logInfo("Success.");
|
logInfo("Success.");
|
||||||
|
|
||||||
exitEventLoop(true);
|
exitEventLoop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ set -e -x -o pipefail
|
||||||
|
|
||||||
DUB_FLAGS=${DUB_FLAGS:-}
|
DUB_FLAGS=${DUB_FLAGS:-}
|
||||||
|
|
||||||
|
# Check for trailing whitespace"
|
||||||
|
grep -nrI --include='*.d' '\s$' . && (echo "Trailing whitespace found"; exit 1)
|
||||||
|
|
||||||
# test for successful release build
|
# test for successful release build
|
||||||
dub build -b release --compiler=$DC -c $CONFIG $DUB_FLAGS
|
dub build -b release --compiler=$DC -c $CONFIG $DUB_FLAGS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue