Lesson 35 - Get Compute Auth Token Working
This commit is contained in:
@@ -0,0 +1,756 @@
|
||||
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#ifndef DLIB_PIPE_KERNEl_1_
|
||||
#define DLIB_PIPE_KERNEl_1_
|
||||
|
||||
#include "../algs.h"
|
||||
#include "../threads.h"
|
||||
#include "pipe_kernel_abstract.h"
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
class pipe
|
||||
{
|
||||
/*!
|
||||
INITIAL VALUE
|
||||
- pipe_size == 0
|
||||
- pipe_max_size == defined by constructor
|
||||
- enabled == true
|
||||
- data == a pointer to an array of ((pipe_max_size>0)?pipe_max_size:1) T objects.
|
||||
- dequeue_waiters == 0
|
||||
- enqueue_waiters == 0
|
||||
- first == 1
|
||||
- last == 1
|
||||
- unblock_sig_waiters == 0
|
||||
|
||||
CONVENTION
|
||||
- size() == pipe_size
|
||||
- max_size() == pipe_max_size
|
||||
- is_enabled() == enabled
|
||||
|
||||
- m == the mutex used to lock access to all the members of this class
|
||||
|
||||
- dequeue_waiters == the number of threads blocked on calls to dequeue()
|
||||
- enqueue_waiters == the number of threads blocked on calls to enqueue() and
|
||||
wait_until_empty()
|
||||
- unblock_sig_waiters == the number of threads blocked on calls to
|
||||
wait_for_num_blocked_dequeues() and the destructor. (i.e. the number of
|
||||
blocking calls to unblock_sig.wait())
|
||||
|
||||
- dequeue_sig == the signaler that threads blocked on calls to dequeue() wait on
|
||||
- enqueue_sig == the signaler that threads blocked on calls to enqueue()
|
||||
or wait_until_empty() wait on.
|
||||
- unblock_sig == the signaler that is signaled when a thread stops blocking on a call
|
||||
to enqueue() or dequeue(). It is also signaled when a dequeue that will probably
|
||||
block is called. The destructor and wait_for_num_blocked_dequeues are the only
|
||||
things that will wait on this signaler.
|
||||
|
||||
- if (pipe_size > 0) then
|
||||
- data[first] == the next item to dequeue
|
||||
- data[last] == the item most recently added via enqueue, so the last to dequeue.
|
||||
- else if (pipe_max_size == 0)
|
||||
- if (first == 0 && last == 0) then
|
||||
- data[0] == the next item to dequeue
|
||||
- else if (first == 0 && last == 1) then
|
||||
- data[0] has been taken out already by a dequeue
|
||||
!*/
|
||||
|
||||
public:
|
||||
// this is here for backwards compatibility with older versions of dlib.
|
||||
typedef pipe kernel_1a;
|
||||
|
||||
typedef T type;
|
||||
|
||||
explicit pipe (
|
||||
size_t maximum_size
|
||||
);
|
||||
|
||||
virtual ~pipe (
|
||||
);
|
||||
|
||||
void empty (
|
||||
);
|
||||
|
||||
void wait_until_empty (
|
||||
) const;
|
||||
|
||||
void wait_for_num_blocked_dequeues (
|
||||
unsigned long num
|
||||
)const;
|
||||
|
||||
void enable (
|
||||
);
|
||||
|
||||
void disable (
|
||||
);
|
||||
|
||||
bool is_enqueue_enabled (
|
||||
) const;
|
||||
|
||||
void disable_enqueue (
|
||||
);
|
||||
|
||||
void enable_enqueue (
|
||||
);
|
||||
|
||||
bool is_dequeue_enabled (
|
||||
) const;
|
||||
|
||||
void disable_dequeue (
|
||||
);
|
||||
|
||||
void enable_dequeue (
|
||||
);
|
||||
|
||||
bool is_enabled (
|
||||
) const;
|
||||
|
||||
size_t max_size (
|
||||
) const;
|
||||
|
||||
size_t size (
|
||||
) const;
|
||||
|
||||
bool enqueue (
|
||||
T& item
|
||||
);
|
||||
|
||||
bool enqueue (
|
||||
T&& item
|
||||
) { return enqueue(item); }
|
||||
|
||||
bool dequeue (
|
||||
T& item
|
||||
);
|
||||
|
||||
bool enqueue_or_timeout (
|
||||
T& item,
|
||||
unsigned long timeout
|
||||
);
|
||||
|
||||
bool enqueue_or_timeout (
|
||||
T&& item,
|
||||
unsigned long timeout
|
||||
) { return enqueue_or_timeout(item,timeout); }
|
||||
|
||||
bool dequeue_or_timeout (
|
||||
T& item,
|
||||
unsigned long timeout
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
size_t pipe_size;
|
||||
const size_t pipe_max_size;
|
||||
bool enabled;
|
||||
|
||||
T* const data;
|
||||
|
||||
size_t first;
|
||||
size_t last;
|
||||
|
||||
mutex m;
|
||||
signaler dequeue_sig;
|
||||
signaler enqueue_sig;
|
||||
signaler unblock_sig;
|
||||
|
||||
unsigned long dequeue_waiters;
|
||||
mutable unsigned long enqueue_waiters;
|
||||
mutable unsigned long unblock_sig_waiters;
|
||||
bool enqueue_enabled;
|
||||
bool dequeue_enabled;
|
||||
|
||||
// restricted functions
|
||||
pipe(const pipe&); // copy constructor
|
||||
pipe& operator=(const pipe&); // assignment operator
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// member function definitions
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
pipe<T>::
|
||||
pipe (
|
||||
size_t maximum_size
|
||||
) :
|
||||
pipe_size(0),
|
||||
pipe_max_size(maximum_size),
|
||||
enabled(true),
|
||||
data(new T[(maximum_size>0) ? maximum_size : 1]),
|
||||
first(1),
|
||||
last(1),
|
||||
dequeue_sig(m),
|
||||
enqueue_sig(m),
|
||||
unblock_sig(m),
|
||||
dequeue_waiters(0),
|
||||
enqueue_waiters(0),
|
||||
unblock_sig_waiters(0),
|
||||
enqueue_enabled(true),
|
||||
dequeue_enabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
pipe<T>::
|
||||
~pipe (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
++unblock_sig_waiters;
|
||||
|
||||
// first make sure no one is blocked on any calls to enqueue() or dequeue()
|
||||
enabled = false;
|
||||
dequeue_sig.broadcast();
|
||||
enqueue_sig.broadcast();
|
||||
unblock_sig.broadcast();
|
||||
|
||||
// wait for all threads to unblock
|
||||
while (dequeue_waiters > 0 || enqueue_waiters > 0 || unblock_sig_waiters > 1)
|
||||
unblock_sig.wait();
|
||||
|
||||
delete [] data;
|
||||
--unblock_sig_waiters;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
empty (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
pipe_size = 0;
|
||||
|
||||
// let any calls to enqueue() know that the pipe is now empty
|
||||
if (enqueue_waiters > 0)
|
||||
enqueue_sig.broadcast();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
wait_until_empty (
|
||||
) const
|
||||
{
|
||||
auto_mutex M(m);
|
||||
// this function is sort of like a call to enqueue so treat it like that
|
||||
++enqueue_waiters;
|
||||
|
||||
while (pipe_size > 0 && enabled && dequeue_enabled )
|
||||
enqueue_sig.wait();
|
||||
|
||||
// let the destructor know we are ending if it is blocked waiting
|
||||
if (enabled == false)
|
||||
unblock_sig.broadcast();
|
||||
|
||||
--enqueue_waiters;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
enable (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
disable (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
enabled = false;
|
||||
dequeue_sig.broadcast();
|
||||
enqueue_sig.broadcast();
|
||||
unblock_sig.broadcast();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
bool pipe<T>::
|
||||
is_enabled (
|
||||
) const
|
||||
{
|
||||
auto_mutex M(m);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
size_t pipe<T>::
|
||||
max_size (
|
||||
) const
|
||||
{
|
||||
auto_mutex M(m);
|
||||
return pipe_max_size;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
size_t pipe<T>::
|
||||
size (
|
||||
) const
|
||||
{
|
||||
auto_mutex M(m);
|
||||
return pipe_size;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
bool pipe<T>::
|
||||
enqueue (
|
||||
T& item
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
++enqueue_waiters;
|
||||
|
||||
// wait until there is room or we are disabled
|
||||
while (pipe_size == pipe_max_size && enabled && enqueue_enabled &&
|
||||
!(pipe_max_size == 0 && first == 1) )
|
||||
enqueue_sig.wait();
|
||||
|
||||
if (enabled == false || enqueue_enabled == false)
|
||||
{
|
||||
--enqueue_waiters;
|
||||
// let the destructor know we are unblocking
|
||||
unblock_sig.broadcast();
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the appropriate values for first and last
|
||||
if (pipe_size == 0)
|
||||
{
|
||||
first = 0;
|
||||
last = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
last = (last+1)%pipe_max_size;
|
||||
}
|
||||
|
||||
|
||||
exchange(item,data[last]);
|
||||
|
||||
// wake up a call to dequeue() if there are any currently blocked
|
||||
if (dequeue_waiters > 0)
|
||||
dequeue_sig.signal();
|
||||
|
||||
if (pipe_max_size > 0)
|
||||
{
|
||||
++pipe_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// wait for a dequeue to take the item out
|
||||
while (last == 0 && enabled && enqueue_enabled)
|
||||
enqueue_sig.wait();
|
||||
|
||||
if (last == 0 && (enabled == false || enqueue_enabled == false))
|
||||
{
|
||||
last = 1;
|
||||
first = 1;
|
||||
|
||||
// no one dequeued this object to put it back into item
|
||||
exchange(item,data[0]);
|
||||
|
||||
--enqueue_waiters;
|
||||
// let the destructor know we are unblocking
|
||||
if (unblock_sig_waiters > 0)
|
||||
unblock_sig.broadcast();
|
||||
return false;
|
||||
}
|
||||
|
||||
last = 1;
|
||||
first = 1;
|
||||
|
||||
// tell any waiting calls to enqueue() that one of them can proceed
|
||||
if (enqueue_waiters > 1)
|
||||
enqueue_sig.broadcast();
|
||||
|
||||
// let the destructor know we are unblocking
|
||||
if (enabled == false && unblock_sig_waiters > 0)
|
||||
unblock_sig.broadcast();
|
||||
}
|
||||
|
||||
--enqueue_waiters;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
bool pipe<T>::
|
||||
dequeue (
|
||||
T& item
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
++dequeue_waiters;
|
||||
|
||||
if (pipe_size == 0)
|
||||
{
|
||||
// notify wait_for_num_blocked_dequeues()
|
||||
if (unblock_sig_waiters > 0)
|
||||
unblock_sig.broadcast();
|
||||
|
||||
// notify any blocked enqueue_or_timeout() calls
|
||||
if (enqueue_waiters > 0)
|
||||
enqueue_sig.broadcast();
|
||||
}
|
||||
|
||||
// wait until there is something in the pipe or we are disabled
|
||||
while (pipe_size == 0 && enabled && dequeue_enabled &&
|
||||
!(pipe_max_size == 0 && first == 0 && last == 0) )
|
||||
dequeue_sig.wait();
|
||||
|
||||
if (enabled == false || dequeue_enabled == false)
|
||||
{
|
||||
--dequeue_waiters;
|
||||
// let the destructor know we are unblocking
|
||||
unblock_sig.broadcast();
|
||||
return false;
|
||||
}
|
||||
|
||||
exchange(item,data[first]);
|
||||
|
||||
if (pipe_max_size > 0)
|
||||
{
|
||||
// set the appropriate values for first
|
||||
first = (first+1)%pipe_max_size;
|
||||
|
||||
--pipe_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// let the enqueue waiting on us know that we took the
|
||||
// item out already.
|
||||
last = 1;
|
||||
}
|
||||
|
||||
// wake up a call to enqueue() if there are any currently blocked
|
||||
if (enqueue_waiters > 0)
|
||||
enqueue_sig.broadcast();
|
||||
|
||||
--dequeue_waiters;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
bool pipe<T>::
|
||||
enqueue_or_timeout (
|
||||
T& item,
|
||||
unsigned long timeout
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
++enqueue_waiters;
|
||||
|
||||
// wait until there is room or we are disabled or
|
||||
// we run out of time.
|
||||
bool timed_out = false;
|
||||
while (pipe_size == pipe_max_size && enabled && enqueue_enabled &&
|
||||
!(pipe_max_size == 0 && dequeue_waiters > 0 && first == 1) )
|
||||
{
|
||||
if (timeout == 0 || enqueue_sig.wait_or_timeout(timeout) == false)
|
||||
{
|
||||
timed_out = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled == false || timed_out || enqueue_enabled == false)
|
||||
{
|
||||
--enqueue_waiters;
|
||||
// let the destructor know we are unblocking
|
||||
unblock_sig.broadcast();
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the appropriate values for first and last
|
||||
if (pipe_size == 0)
|
||||
{
|
||||
first = 0;
|
||||
last = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
last = (last+1)%pipe_max_size;
|
||||
}
|
||||
|
||||
|
||||
exchange(item,data[last]);
|
||||
|
||||
// wake up a call to dequeue() if there are any currently blocked
|
||||
if (dequeue_waiters > 0)
|
||||
dequeue_sig.signal();
|
||||
|
||||
if (pipe_max_size > 0)
|
||||
{
|
||||
++pipe_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// wait for a dequeue to take the item out
|
||||
while (last == 0 && enabled && enqueue_enabled)
|
||||
enqueue_sig.wait();
|
||||
|
||||
if (last == 0 && (enabled == false || enqueue_enabled == false))
|
||||
{
|
||||
last = 1;
|
||||
first = 1;
|
||||
|
||||
// no one dequeued this object to put it back into item
|
||||
exchange(item,data[0]);
|
||||
|
||||
--enqueue_waiters;
|
||||
// let the destructor know we are unblocking
|
||||
if (unblock_sig_waiters > 0)
|
||||
unblock_sig.broadcast();
|
||||
return false;
|
||||
}
|
||||
|
||||
last = 1;
|
||||
first = 1;
|
||||
|
||||
// tell any waiting calls to enqueue() that one of them can proceed
|
||||
if (enqueue_waiters > 1)
|
||||
enqueue_sig.broadcast();
|
||||
|
||||
// let the destructor know we are unblocking
|
||||
if (enabled == false && unblock_sig_waiters > 0)
|
||||
unblock_sig.broadcast();
|
||||
}
|
||||
|
||||
--enqueue_waiters;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
bool pipe<T>::
|
||||
dequeue_or_timeout (
|
||||
T& item,
|
||||
unsigned long timeout
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
++dequeue_waiters;
|
||||
|
||||
if (pipe_size == 0)
|
||||
{
|
||||
// notify wait_for_num_blocked_dequeues()
|
||||
if (unblock_sig_waiters > 0)
|
||||
unblock_sig.broadcast();
|
||||
|
||||
// notify any blocked enqueue_or_timeout() calls
|
||||
if (enqueue_waiters > 0)
|
||||
enqueue_sig.broadcast();
|
||||
}
|
||||
|
||||
bool timed_out = false;
|
||||
// wait until there is something in the pipe or we are disabled or we timeout.
|
||||
while (pipe_size == 0 && enabled && dequeue_enabled &&
|
||||
!(pipe_max_size == 0 && first == 0 && last == 0) )
|
||||
{
|
||||
if (timeout == 0 || dequeue_sig.wait_or_timeout(timeout) == false)
|
||||
{
|
||||
timed_out = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled == false || timed_out || dequeue_enabled == false)
|
||||
{
|
||||
--dequeue_waiters;
|
||||
// let the destructor know we are unblocking
|
||||
unblock_sig.broadcast();
|
||||
return false;
|
||||
}
|
||||
|
||||
exchange(item,data[first]);
|
||||
|
||||
if (pipe_max_size > 0)
|
||||
{
|
||||
// set the appropriate values for first
|
||||
first = (first+1)%pipe_max_size;
|
||||
|
||||
--pipe_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// let the enqueue waiting on us know that we took the
|
||||
// item out already.
|
||||
last = 1;
|
||||
}
|
||||
|
||||
// wake up a call to enqueue() if there are any currently blocked
|
||||
if (enqueue_waiters > 0)
|
||||
enqueue_sig.broadcast();
|
||||
|
||||
--dequeue_waiters;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
wait_for_num_blocked_dequeues (
|
||||
unsigned long num
|
||||
)const
|
||||
{
|
||||
auto_mutex M(m);
|
||||
++unblock_sig_waiters;
|
||||
|
||||
while ( (dequeue_waiters < num || pipe_size != 0) && enabled && dequeue_enabled)
|
||||
unblock_sig.wait();
|
||||
|
||||
// let the destructor know we are ending if it is blocked waiting
|
||||
if (enabled == false)
|
||||
unblock_sig.broadcast();
|
||||
|
||||
--unblock_sig_waiters;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
bool pipe<T>::
|
||||
is_enqueue_enabled (
|
||||
) const
|
||||
{
|
||||
auto_mutex M(m);
|
||||
return enqueue_enabled;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
disable_enqueue (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
enqueue_enabled = false;
|
||||
enqueue_sig.broadcast();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
enable_enqueue (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
enqueue_enabled = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
bool pipe<T>::
|
||||
is_dequeue_enabled (
|
||||
) const
|
||||
{
|
||||
auto_mutex M(m);
|
||||
return dequeue_enabled;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
disable_dequeue (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
dequeue_enabled = false;
|
||||
dequeue_sig.broadcast();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void pipe<T>::
|
||||
enable_dequeue (
|
||||
)
|
||||
{
|
||||
auto_mutex M(m);
|
||||
dequeue_enabled = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_PIPE_KERNEl_1_
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#undef DLIB_PIPE_KERNEl_ABSTRACT_
|
||||
#ifdef DLIB_PIPE_KERNEl_ABSTRACT_
|
||||
|
||||
#include "../threads.h"
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
class pipe
|
||||
{
|
||||
/*!
|
||||
REQUIREMENTS ON T
|
||||
T must be swappable by a global swap()
|
||||
T must have a default constructor
|
||||
|
||||
INITIAL VALUE
|
||||
size() == 0
|
||||
is_enabled() == true
|
||||
is_enqueue_enabled() == true
|
||||
is_dequeue_enabled() == true
|
||||
|
||||
WHAT THIS OBJECT REPRESENTS
|
||||
This is a first in first out queue with a fixed maximum size containing
|
||||
items of type T. It is suitable for passing objects between threads.
|
||||
|
||||
THREAD SAFETY
|
||||
All methods of this class are thread safe. You may call them from any
|
||||
thread and any number of threads my call them at once.
|
||||
!*/
|
||||
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
|
||||
explicit pipe (
|
||||
size_t maximum_size
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #*this is properly initialized
|
||||
- #max_size() == maximum_size
|
||||
throws
|
||||
- std::bad_alloc
|
||||
- dlib::thread_error
|
||||
!*/
|
||||
|
||||
virtual ~pipe (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- any resources associated with *this have been released
|
||||
- disables (i.e. sets is_enabled() == false) this object so that
|
||||
all calls currently blocking on it will return immediately.
|
||||
!*/
|
||||
|
||||
void enable (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #is_enabled() == true
|
||||
!*/
|
||||
|
||||
void disable (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #is_enabled() == false
|
||||
- causes all current and future calls to enqueue(), dequeue(),
|
||||
enqueue_or_timeout() and dequeue_or_timeout() to not block but
|
||||
to return false immediately until enable() is called.
|
||||
- causes all current and future calls to wait_until_empty() and
|
||||
wait_for_num_blocked_dequeues() to not block but return
|
||||
immediately until enable() is called.
|
||||
!*/
|
||||
|
||||
bool is_enabled (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns true if this pipe is currently enabled, false otherwise.
|
||||
!*/
|
||||
|
||||
void empty (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #size() == 0
|
||||
!*/
|
||||
|
||||
void wait_until_empty (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- blocks until one of the following is the case:
|
||||
- size() == 0
|
||||
- is_enabled() == false
|
||||
- is_dequeue_enabled() == false
|
||||
!*/
|
||||
|
||||
void wait_for_num_blocked_dequeues (
|
||||
unsigned long num
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- blocks until one of the following is the case:
|
||||
- size() == 0 and the number of threads blocked on calls
|
||||
to dequeue() and dequeue_or_timeout() is greater than
|
||||
or equal to num.
|
||||
- is_enabled() == false
|
||||
- is_dequeue_enabled() == false
|
||||
!*/
|
||||
|
||||
bool is_enqueue_enabled (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns true if the enqueue() and enqueue_or_timeout() functions are
|
||||
currently enabled, returns false otherwise. (note that the higher
|
||||
level is_enabled() function can overrule this one. So if
|
||||
is_enabled() == false then enqueue functions are still disabled even
|
||||
if is_enqueue_enabled() returns true. But if is_enqueue_enabled() == false
|
||||
then enqueue functions are always disabled no matter the state of
|
||||
is_enabled())
|
||||
!*/
|
||||
|
||||
void disable_enqueue (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #is_enqueue_enabled() == false
|
||||
- causes all current and future calls to enqueue() and
|
||||
enqueue_or_timeout() to not block but to return false
|
||||
immediately until enable_enqueue() is called.
|
||||
!*/
|
||||
|
||||
void enable_enqueue (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #is_enqueue_enabled() == true
|
||||
!*/
|
||||
|
||||
bool is_dequeue_enabled (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns true if the dequeue() and dequeue_or_timeout() functions are
|
||||
currently enabled, returns false otherwise. (note that the higher
|
||||
level is_enabled() function can overrule this one. So if
|
||||
is_enabled() == false then dequeue functions are still disabled even
|
||||
if is_dequeue_enabled() returns true. But if is_dequeue_enabled() == false
|
||||
then dequeue functions are always disabled no matter the state of
|
||||
is_enabled())
|
||||
!*/
|
||||
|
||||
void disable_dequeue (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #is_dequeue_enabled() == false
|
||||
- causes all current and future calls to dequeue() and
|
||||
dequeue_or_timeout() to not block but to return false
|
||||
immediately until enable_dequeue() is called.
|
||||
!*/
|
||||
|
||||
void enable_dequeue (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #is_dequeue_enabled() == true
|
||||
!*/
|
||||
|
||||
size_t max_size (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns the maximum number of objects of type T that this
|
||||
pipe can contain.
|
||||
!*/
|
||||
|
||||
size_t size (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns the number of objects of type T that this
|
||||
object currently contains.
|
||||
!*/
|
||||
|
||||
bool enqueue (
|
||||
T& item
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- if (size() == max_size()) then
|
||||
- this call to enqueue() blocks until one of the following is the case:
|
||||
- there is room in the pipe for another item
|
||||
- max_size() == 0 and another thread is trying to dequeue from this
|
||||
pipe and we can pass our item object directly to that thread.
|
||||
- someone calls disable()
|
||||
- someone calls disable_enqueue()
|
||||
- else
|
||||
- this call does not block.
|
||||
- if (this call to enqueue() returns true) then
|
||||
- #is_enabled() == true
|
||||
- #is_enqueue_enabled() == true
|
||||
- if (max_size() == 0) then
|
||||
- using global swap, item was passed directly to a
|
||||
thread attempting to dequeue from this pipe
|
||||
- else
|
||||
- using global swap, item was added into this pipe.
|
||||
- #item is in an undefined but valid state for its type
|
||||
- else
|
||||
- item was NOT added into the pipe
|
||||
- #item == item (i.e. the value of item is unchanged)
|
||||
!*/
|
||||
|
||||
bool enqueue (T&& item) { return enqueue(item); }
|
||||
/*!
|
||||
enable enqueueing from rvalues
|
||||
!*/
|
||||
|
||||
bool enqueue_or_timeout (
|
||||
T& item,
|
||||
unsigned long timeout
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- if (size() == max_size() && timeout > 0) then
|
||||
- this call to enqueue_or_timeout() blocks until one of the following is the case:
|
||||
- there is room in the pipe to add another item
|
||||
- max_size() == 0 and another thread is trying to dequeue from this pipe
|
||||
and we can pass our item object directly to that thread.
|
||||
- someone calls disable()
|
||||
- someone calls disable_enqueue()
|
||||
- timeout milliseconds passes
|
||||
- else
|
||||
- this call does not block.
|
||||
- if (this call to enqueue() returns true) then
|
||||
- #is_enabled() == true
|
||||
- #is_enqueue_enabled() == true
|
||||
- if (max_size() == 0) then
|
||||
- using global swap, item was passed directly to a
|
||||
thread attempting to dequeue from this pipe
|
||||
- else
|
||||
- using global swap, item was added into this pipe.
|
||||
- #item is in an undefined but valid state for its type
|
||||
- else
|
||||
- item was NOT added into the pipe
|
||||
- #item == item (i.e. the value of item is unchanged)
|
||||
!*/
|
||||
|
||||
bool enqueue_or_timeout (T&& item, unsigned long timeout) { return enqueue_or_timeout(item,timeout); }
|
||||
/*!
|
||||
enable enqueueing from rvalues
|
||||
!*/
|
||||
|
||||
bool dequeue (
|
||||
T& item
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- if (size() == 0) then
|
||||
- this call to dequeue() blocks until one of the following is the case:
|
||||
- there is something in the pipe we can dequeue
|
||||
- max_size() == 0 and another thread is trying to enqueue an item
|
||||
onto this pipe and we can receive our item directly from that thread.
|
||||
- someone calls disable()
|
||||
- someone calls disable_dequeue()
|
||||
- else
|
||||
- this call does not block.
|
||||
- if (this call to dequeue() returns true) then
|
||||
- #is_enabled() == true
|
||||
- #is_dequeue_enabled() == true
|
||||
- the oldest item that was enqueued into this pipe has been
|
||||
swapped into #item.
|
||||
- else
|
||||
- nothing was dequeued from this pipe.
|
||||
- #item == item (i.e. the value of item is unchanged)
|
||||
!*/
|
||||
|
||||
bool dequeue_or_timeout (
|
||||
T& item,
|
||||
unsigned long timeout
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- if (size() == 0 && timeout > 0) then
|
||||
- this call to dequeue_or_timeout() blocks until one of the following is the case:
|
||||
- there is something in the pipe we can dequeue
|
||||
- max_size() == 0 and another thread is trying to enqueue an item onto this
|
||||
pipe and we can receive our item directly from that thread.
|
||||
- someone calls disable()
|
||||
- someone calls disable_dequeue()
|
||||
- timeout milliseconds passes
|
||||
- else
|
||||
- this call does not block.
|
||||
- if (this call to dequeue_or_timeout() returns true) then
|
||||
- #is_enabled() == true
|
||||
- #is_dequeue_enabled() == true
|
||||
- the oldest item that was enqueued into this pipe has been
|
||||
swapped into #item.
|
||||
- else
|
||||
- nothing was dequeued from this pipe.
|
||||
- #item == item (i.e. the value of item is unchanged)
|
||||
!*/
|
||||
|
||||
private:
|
||||
|
||||
// restricted functions
|
||||
pipe(const pipe&); // copy constructor
|
||||
pipe& operator=(const pipe&); // assignment operator
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_PIPE_KERNEl_ABSTRACT_
|
||||
|
||||
Reference in New Issue
Block a user