doc ru, printf() before assert in containers
This commit is contained in:
@@ -2,8 +2,5 @@
|
|||||||
|
|
||||||
void _() {
|
void _() {
|
||||||
//! [main]
|
//! [main]
|
||||||
mutex.lock();
|
|
||||||
// ... your code here
|
|
||||||
mutex.unlock();
|
|
||||||
//! [main]
|
//! [main]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -440,6 +440,11 @@ public:
|
|||||||
}
|
}
|
||||||
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
|
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
|
||||||
if (other.isEmpty()) return *this;
|
if (other.isEmpty()) return *this;
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (&other == this) {
|
||||||
|
printf("error with PIDeque<%s>::insert\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(&other != this);
|
assert(&other != this);
|
||||||
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
@@ -544,6 +549,11 @@ public:
|
|||||||
inline PIDeque<T> & append(const T & e) {return push_back(e);}
|
inline PIDeque<T> & append(const T & e) {return push_back(e);}
|
||||||
inline PIDeque<T> & append(T && e) {return push_back(std::move(e));}
|
inline PIDeque<T> & append(T && e) {return push_back(std::move(e));}
|
||||||
inline PIDeque<T> & append(const PIDeque<T> & v) {
|
inline PIDeque<T> & append(const PIDeque<T> & v) {
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (&v == this) {
|
||||||
|
printf("error with PIDeque<%s>::append\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(&v != this);
|
assert(&v != this);
|
||||||
size_t ps = pid_size;
|
size_t ps = pid_size;
|
||||||
alloc(pid_size + v.pid_size, true);
|
alloc(pid_size + v.pid_size, true);
|
||||||
@@ -615,6 +625,11 @@ public:
|
|||||||
inline PIDeque<PIDeque<T>> reshape(size_t rows, size_t cols, int order = byRow) const {
|
inline PIDeque<PIDeque<T>> reshape(size_t rows, size_t cols, int order = byRow) const {
|
||||||
PIDeque<PIDeque<T>> ret;
|
PIDeque<PIDeque<T>> ret;
|
||||||
if (isEmpty()) return ret;
|
if (isEmpty()) return ret;
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (rows*cols != pid_size) {
|
||||||
|
printf("error with PIDeque<%s>::reshape\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(rows*cols == pid_size);
|
assert(rows*cols == pid_size);
|
||||||
ret.resize(rows);
|
ret.resize(rows);
|
||||||
if (order == byRow) {
|
if (order == byRow) {
|
||||||
@@ -762,6 +777,11 @@ private:
|
|||||||
if (as != pid_rsize) {
|
if (as != pid_rsize) {
|
||||||
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
|
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
|
||||||
T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T)));
|
T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T)));
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (!p_d) {
|
||||||
|
printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(p_d);
|
assert(p_d);
|
||||||
pid_data = p_d;
|
pid_data = p_d;
|
||||||
pid_rsize = as;
|
pid_rsize = as;
|
||||||
|
|||||||
@@ -208,6 +208,11 @@ public:
|
|||||||
const T at(const Key & key) const {return (*this)[key];}
|
const T at(const Key & key) const {return (*this)[key];}
|
||||||
|
|
||||||
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
|
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (&other == this) {
|
||||||
|
printf("error with PIMap<%s, %s>::<<\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(&other != this);
|
assert(&other != this);
|
||||||
if (other.isEmpty()) return *this;
|
if (other.isEmpty()) return *this;
|
||||||
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
|
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
|
||||||
|
|||||||
@@ -1199,6 +1199,11 @@ public:
|
|||||||
//! \~\sa \a append(), \a prepend(), \a remove()
|
//! \~\sa \a append(), \a prepend(), \a remove()
|
||||||
inline PIVector<T> & insert(size_t index, const PIVector<T> & v) {
|
inline PIVector<T> & insert(size_t index, const PIVector<T> & v) {
|
||||||
if (v.isEmpty()) return *this;
|
if (v.isEmpty()) return *this;
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (&v == this) {
|
||||||
|
printf("error with PIVector<%s>::insert\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(&v != this);
|
assert(&v != this);
|
||||||
ssize_t os = piv_size - index;
|
ssize_t os = piv_size - index;
|
||||||
alloc(piv_size + v.piv_size);
|
alloc(piv_size + v.piv_size);
|
||||||
@@ -1385,6 +1390,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline PIVector<T> & push_back(const PIVector<T> & v) {
|
inline PIVector<T> & push_back(const PIVector<T> & v) {
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (&v == this) {
|
||||||
|
printf("error with PIVector<%s>::push_back\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(&v != this);
|
assert(&v != this);
|
||||||
size_t ps = piv_size;
|
size_t ps = piv_size;
|
||||||
alloc(piv_size + v.piv_size);
|
alloc(piv_size + v.piv_size);
|
||||||
@@ -1485,6 +1495,11 @@ public:
|
|||||||
inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = byRow) const {
|
inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = byRow) const {
|
||||||
PIVector<PIVector<T>> ret;
|
PIVector<PIVector<T>> ret;
|
||||||
if (isEmpty()) return ret;
|
if (isEmpty()) return ret;
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (rows*cols != piv_size) {
|
||||||
|
printf("error with PIVector<%s>::reshape\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(rows*cols == piv_size);
|
assert(rows*cols == piv_size);
|
||||||
ret.resize(rows);
|
ret.resize(rows);
|
||||||
if (order == byRow) {
|
if (order == byRow) {
|
||||||
@@ -1609,6 +1624,11 @@ private:
|
|||||||
if (as == piv_rsize) return;
|
if (as == piv_rsize) return;
|
||||||
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-piv_rsize))
|
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-piv_rsize))
|
||||||
T * p_d = (T*)(realloc((void*)(piv_data), as*sizeof(T)));
|
T * p_d = (T*)(realloc((void*)(piv_data), as*sizeof(T)));
|
||||||
|
#ifdef USE_DEBUG
|
||||||
|
if (!p_d) {
|
||||||
|
printf("error with PIVector<%s>::alloc\n", __PIP_TYPENAME__(T));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assert(p_d);
|
assert(p_d);
|
||||||
piv_data = p_d;
|
piv_data = p_d;
|
||||||
piv_rsize = as;
|
piv_rsize = as;
|
||||||
|
|||||||
@@ -248,6 +248,8 @@
|
|||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
# undef NDEBUG
|
# undef NDEBUG
|
||||||
|
#else
|
||||||
|
# define USE_DEBUG
|
||||||
#endif
|
#endif
|
||||||
#ifndef assert
|
#ifndef assert
|
||||||
# define assert(x)
|
# define assert(x)
|
||||||
@@ -256,6 +258,12 @@
|
|||||||
# define assertm(exp, msg) assert(((void)msg, exp))
|
# define assertm(exp, msg) assert(((void)msg, exp))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MICRO_PIP
|
||||||
|
# define __PIP_TYPENAME__(T) "?"
|
||||||
|
#else
|
||||||
|
# define __PIP_TYPENAME__(T) typeid(T).name()
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CC_GCC
|
#ifdef CC_GCC
|
||||||
# undef DEPRECATED
|
# undef DEPRECATED
|
||||||
# define DEPRECATED __attribute__((deprecated))
|
# define DEPRECATED __attribute__((deprecated))
|
||||||
|
|||||||
@@ -32,12 +32,6 @@
|
|||||||
#include "pivector2d.h"
|
#include "pivector2d.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef MICRO_PIP
|
|
||||||
# define _TYPENAME_(T) "?"
|
|
||||||
#else
|
|
||||||
# define _TYPENAME_(T) typeid(T).name()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class PIString;
|
class PIString;
|
||||||
class PIByteArray;
|
class PIByteArray;
|
||||||
|
|
||||||
@@ -394,7 +388,7 @@ inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >=
|
|||||||
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
|
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
|
||||||
if (s.size() < sizeof(v)) {
|
if (s.size() < sizeof(v)) {
|
||||||
printf("error with %s\n", _TYPENAME_(T));
|
printf("error with %s\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size() >= sizeof(v));
|
assert(s.size() >= sizeof(v));
|
||||||
}
|
}
|
||||||
memcpy((void*)(&v), s.data(), sizeof(v));
|
memcpy((void*)(&v), s.data(), sizeof(v));
|
||||||
@@ -430,7 +424,7 @@ template<typename T,
|
|||||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||||
if (s.size_s() < 4) {
|
if (s.size_s() < 4) {
|
||||||
printf("error with PIVector<%s>\n", _TYPENAME_(T));
|
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 4);
|
assert(s.size_s() >= 4);
|
||||||
}
|
}
|
||||||
int sz; s >> sz;
|
int sz; s >> sz;
|
||||||
@@ -446,7 +440,7 @@ template<typename T,
|
|||||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||||
if (s.size_s() < 4) {
|
if (s.size_s() < 4) {
|
||||||
printf("error with PIVector<%s>\n", _TYPENAME_(T));
|
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 4);
|
assert(s.size_s() >= 4);
|
||||||
}
|
}
|
||||||
int sz; s >> sz;
|
int sz; s >> sz;
|
||||||
@@ -463,7 +457,7 @@ template<typename T,
|
|||||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||||
if (s.size_s() < 4) {
|
if (s.size_s() < 4) {
|
||||||
printf("error with PIDeque<%s>\n", _TYPENAME_(T));
|
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 4);
|
assert(s.size_s() >= 4);
|
||||||
}
|
}
|
||||||
int sz; s >> sz;
|
int sz; s >> sz;
|
||||||
@@ -479,7 +473,7 @@ template<typename T,
|
|||||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||||
if (s.size_s() < 4) {
|
if (s.size_s() < 4) {
|
||||||
printf("error with PIDeque<%s>\n", _TYPENAME_(T));
|
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 4);
|
assert(s.size_s() >= 4);
|
||||||
}
|
}
|
||||||
int sz; s >> sz;
|
int sz; s >> sz;
|
||||||
@@ -496,7 +490,7 @@ template<typename T,
|
|||||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||||
if (s.size_s() < 8) {
|
if (s.size_s() < 8) {
|
||||||
printf("error with PIVecto2Dr<%s>\n", _TYPENAME_(T));
|
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 8);
|
assert(s.size_s() >= 8);
|
||||||
}
|
}
|
||||||
int r, c; s >> r >> c;
|
int r, c; s >> r >> c;
|
||||||
@@ -513,7 +507,7 @@ template<typename T,
|
|||||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||||
if (s.size_s() < 8) {
|
if (s.size_s() < 8) {
|
||||||
printf("error with PIVecto2Dr<%s>\n", _TYPENAME_(T));
|
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 8);
|
assert(s.size_s() >= 8);
|
||||||
}
|
}
|
||||||
int r,c;
|
int r,c;
|
||||||
@@ -581,7 +575,7 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
|||||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||||
if (s.size_s() < 4) {
|
if (s.size_s() < 4) {
|
||||||
printf("error with PIVector<%s>\n", _TYPENAME_(T));
|
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 4);
|
assert(s.size_s() >= 4);
|
||||||
}
|
}
|
||||||
int sz; s >> sz;
|
int sz; s >> sz;
|
||||||
@@ -596,7 +590,7 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
|||||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||||
if (s.size_s() < 4) {
|
if (s.size_s() < 4) {
|
||||||
printf("error with PIDeque<%s>\n", _TYPENAME_(T));
|
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 4);
|
assert(s.size_s() >= 4);
|
||||||
}
|
}
|
||||||
int sz; s >> sz;
|
int sz; s >> sz;
|
||||||
@@ -611,7 +605,7 @@ inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
|||||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||||
if (s.size_s() < 8) {
|
if (s.size_s() < 8) {
|
||||||
printf("error with PIVecto2Dr<%s>\n", _TYPENAME_(T));
|
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 8);
|
assert(s.size_s() >= 8);
|
||||||
}
|
}
|
||||||
int r,c;
|
int r,c;
|
||||||
@@ -646,7 +640,7 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
|
|||||||
template <typename Key, typename T>
|
template <typename Key, typename T>
|
||||||
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
|
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
|
||||||
if (s.size_s() < 4) {
|
if (s.size_s() < 4) {
|
||||||
printf("error with PIMap<%s, %s>\n", _TYPENAME_(Key), _TYPENAME_(T));
|
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
|
||||||
assert(s.size_s() >= 4);
|
assert(s.size_s() >= 4);
|
||||||
}
|
}
|
||||||
int sz; s >> sz; v.pim_index.resize(sz);
|
int sz; s >> sz; v.pim_index.resize(sz);
|
||||||
@@ -711,7 +705,4 @@ template <typename T> T piDeserialize(const PIByteArray & data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#undef _TYPENAME_
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PIBYTEARRAY_H
|
#endif // PIBYTEARRAY_H
|
||||||
|
|||||||
@@ -17,22 +17,67 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \class PIMutex
|
//! \addtogroup Thread
|
||||||
* \brief Mutex
|
//! \{
|
||||||
* \details
|
//! \class PIMutex pimutex.h
|
||||||
* \section PIMutex_sec0 Synopsis
|
//!
|
||||||
* %PIMutex provides synchronization blocks between several threads.
|
//! \~\brief
|
||||||
* Using mutex guarantees execution of some code only one of threads.
|
//! \~english Simple mutex
|
||||||
* Mutex contains logic state and functions to change it: \a lock(),
|
//! \~russian Простой мьютекс
|
||||||
* \a unlock() and \a tryLock().
|
//!
|
||||||
*
|
//!
|
||||||
* \section PIMutex_sec1 Usage
|
//! \~\details
|
||||||
* Block of code that should to be executed only one thread simultaniously
|
//! \~english \section PIMutex_sec0 Synopsis
|
||||||
* should to be started with \a lock() and ended with \a unlock().
|
//! \~russian \section PIMutex_sec0 Краткий обзор
|
||||||
* \snippet pimutex.cpp main
|
//!
|
||||||
* "mutex" in this example is one for all threads.
|
//! \~english
|
||||||
*
|
//! %PIMutex provides synchronization blocks between several threads.
|
||||||
* */
|
//! Using mutex guarantees execution of some code only one of threads.
|
||||||
|
//! Mutex contains logic state and functions to change it: \a lock(),
|
||||||
|
//! \a unlock() and \a tryLock().
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~english \section PIMutex_sec0 Usage
|
||||||
|
//! \~russian \section PIMutex_sec0 Использование
|
||||||
|
//!
|
||||||
|
//! \~english
|
||||||
|
//! Block of code that should to be executed only one thread simultaniously
|
||||||
|
//! should to be started with \a lock() and finished with \a unlock().
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//! \~\code
|
||||||
|
//! mutex.lock();
|
||||||
|
//! // ... your code here
|
||||||
|
//! mutex.unlock();
|
||||||
|
//! \endcode
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
|
||||||
|
//! \addtogroup Thread
|
||||||
|
//! \{
|
||||||
|
//! \class PIMutexLocker pimutex.h
|
||||||
|
//!
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english %PIMutex autolocker
|
||||||
|
//! \~russian Автоблокировщик %PIMutex
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~\details
|
||||||
|
//!
|
||||||
|
//! \~english
|
||||||
|
//! When a PIMutexLocker object is created, it attempts to lock the mutex it is given, if "condition" true.
|
||||||
|
//! When control leaves the scope in which the PIMutexLocker object was created,
|
||||||
|
//! the PIMutexLocker is destructed and the mutex is released, if "condition" true.
|
||||||
|
//! If "condition" false this class do nothing.
|
||||||
|
//! The PIMutexLocker class is non-copyable.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
|
||||||
#include "pimutex.h"
|
#include "pimutex.h"
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
@@ -68,6 +113,11 @@ PIMutex::~PIMutex() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! If mutex is unlocked it set to locked state and returns immediate.
|
||||||
|
//! If mutex is already locked function blocks until mutex will be unlocked
|
||||||
|
//! \~russian
|
||||||
void PIMutex::lock() {
|
void PIMutex::lock() {
|
||||||
#if defined(WINDOWS)
|
#if defined(WINDOWS)
|
||||||
EnterCriticalSection(&(PRIVATE->mutex));
|
EnterCriticalSection(&(PRIVATE->mutex));
|
||||||
@@ -79,6 +129,10 @@ void PIMutex::lock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! In any case this function returns immediate
|
||||||
|
//! \~russian
|
||||||
void PIMutex::unlock() {
|
void PIMutex::unlock() {
|
||||||
#if defined(WINDOWS)
|
#if defined(WINDOWS)
|
||||||
LeaveCriticalSection(&(PRIVATE->mutex));
|
LeaveCriticalSection(&(PRIVATE->mutex));
|
||||||
@@ -90,6 +144,11 @@ void PIMutex::unlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! If mutex is unlocked it set to locked state and returns "true" immediate.
|
||||||
|
//! If mutex is already locked function returns immediate an returns "false"
|
||||||
|
//! \~russian
|
||||||
bool PIMutex::tryLock() {
|
bool PIMutex::tryLock() {
|
||||||
bool ret =
|
bool ret =
|
||||||
#if defined(WINDOWS)
|
#if defined(WINDOWS)
|
||||||
|
|||||||
@@ -34,25 +34,25 @@ class PIP_EXPORT PIMutex
|
|||||||
public:
|
public:
|
||||||
NO_COPY_CLASS(PIMutex)
|
NO_COPY_CLASS(PIMutex)
|
||||||
|
|
||||||
//! Constructs unlocked mutex
|
//! \~english Constructs unlocked mutex
|
||||||
|
//! \~russian Создает незаблокированный мьютекс
|
||||||
explicit PIMutex();
|
explicit PIMutex();
|
||||||
|
|
||||||
//! Destroy mutex
|
//! \~english Destroy mutex
|
||||||
|
//! \~russian Деструктор мьютекса
|
||||||
~PIMutex();
|
~PIMutex();
|
||||||
|
|
||||||
|
|
||||||
//! \brief Lock mutex
|
//! \~english Lock mutex
|
||||||
//! \details If mutex is unlocked it set to locked state and returns immediate.
|
//! \~russian Блокирует мьютекс
|
||||||
//! If mutex is already locked function blocks until mutex will be unlocked
|
|
||||||
void lock();
|
void lock();
|
||||||
|
|
||||||
//! \brief Unlock mutex
|
//! \~english Unlock mutex
|
||||||
//! \details In any case this function returns immediate
|
//! \~russian Разблокирует мьютекс
|
||||||
void unlock() ;
|
void unlock();
|
||||||
|
|
||||||
//! \brief Try to lock mutex
|
//! \~english Try to lock mutex
|
||||||
//! \details If mutex is unlocked it set to locked state and returns "true" immediate.
|
//! \~russian Пробует заблокировать мьютекс
|
||||||
//! If mutex is already locked function returns immediate an returns "false"
|
|
||||||
bool tryLock();
|
bool tryLock();
|
||||||
|
|
||||||
void * handle();
|
void * handle();
|
||||||
@@ -66,22 +66,24 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \brief PIMutexLocker
|
|
||||||
//! \details Same as std::lock_guard<std::mutex>.
|
|
||||||
//! When a PIMutexLocker object is created, it attempts to lock the mutex it is given, if "condition" true.
|
|
||||||
//! When control leaves the scope in which the PIMutexLocker object was created,
|
|
||||||
//! the PIMutexLocker is destructed and the mutex is released, if "condition" true.
|
|
||||||
//! If "condition" false this class do nothing.
|
|
||||||
//! The PIMutexLocker class is non-copyable.
|
|
||||||
class PIP_EXPORT PIMutexLocker
|
class PIP_EXPORT PIMutexLocker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NO_COPY_CLASS(PIMutexLocker)
|
NO_COPY_CLASS(PIMutexLocker)
|
||||||
|
|
||||||
|
//! \~english Constructs and lock "m" if "condition" is \c true
|
||||||
|
//! \~russian
|
||||||
PIMutexLocker(PIMutex & m, bool condition = true): mutex(m), cond(condition) {if (cond) mutex.lock();}
|
PIMutexLocker(PIMutex & m, bool condition = true): mutex(m), cond(condition) {if (cond) mutex.lock();}
|
||||||
|
|
||||||
|
//! \~english Unlock "m" if "condition" was \c true
|
||||||
|
//! \~russian
|
||||||
~PIMutexLocker() {if (cond) mutex.unlock();}
|
~PIMutexLocker() {if (cond) mutex.unlock();}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PIMutex & mutex;
|
PIMutex & mutex;
|
||||||
bool cond;
|
bool cond;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PIMUTEX_H
|
#endif // PIMUTEX_H
|
||||||
|
|||||||
@@ -17,14 +17,49 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \class PISpinlock
|
//! \addtogroup Thread
|
||||||
* \brief Spinlock
|
//! \{
|
||||||
* \details
|
//! \class PISpinlock pispinlock.h
|
||||||
* \section PISpinlock_sec0 Synopsis
|
//!
|
||||||
* %PISpinlock provides synchronization blocks between several threads.
|
//! \~\brief
|
||||||
* PISpinlock functionality similar to PIMutex, but working on atomic
|
//! \~english Fast and full-load lock
|
||||||
* type and \a lock() method wait with 100% CPU load.
|
//! \~russian Быстрая блокировка с полной нагрузкой
|
||||||
* \note
|
//!
|
||||||
* Use this type instead of PIMutex when less waiting time is more
|
//! \~\details
|
||||||
* important than CPU load!
|
//! \~english
|
||||||
* */
|
//! %PISpinlock provides synchronization blocks between several threads.
|
||||||
|
//! PISpinlock functionality similar to PIMutex, but working on atomic
|
||||||
|
//! type and \a lock() method wait with 100% CPU load.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//! \~\note
|
||||||
|
//! \~english
|
||||||
|
//! Use this type instead of PIMutex when less waiting time is more
|
||||||
|
//! important than CPU load!
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
|
||||||
|
//! \addtogroup Thread
|
||||||
|
//! \{
|
||||||
|
//! \class PISpinlockLocker pispinlock.h
|
||||||
|
//!
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english %PISpinlock autolocker
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! When a PISpinlockLocker object is created, it attempts to lock the spinlock it is given, if "condition" true.
|
||||||
|
//! When control leaves the scope in which the PISpinlockLocker object was created,
|
||||||
|
//! the PISpinlockLocker is destructed and the spinlock is released, if "condition" true.
|
||||||
|
//! If "condition" false this class do nothing.
|
||||||
|
//! The PISpinlockLocker class is non-copyable.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//! \}
|
||||||
|
|||||||
@@ -35,20 +35,30 @@ class PIP_EXPORT PISpinlock
|
|||||||
public:
|
public:
|
||||||
NO_COPY_CLASS(PISpinlock)
|
NO_COPY_CLASS(PISpinlock)
|
||||||
|
|
||||||
//! Constructs unlocked spinlock
|
//! \~english Constructs unlocked spinlock
|
||||||
|
//! \~russian
|
||||||
explicit PISpinlock() {flag.clear();}
|
explicit PISpinlock() {flag.clear();}
|
||||||
|
|
||||||
//! Destroy spinlock
|
//! \~english Destroy spinlock
|
||||||
|
//! \~russian
|
||||||
~PISpinlock() {}
|
~PISpinlock() {}
|
||||||
|
|
||||||
|
|
||||||
//! \brief Lock spinlock
|
//! \~english Lock spinlock
|
||||||
//! \details If spinlock is unlocked it set to locked state and returns immediate.
|
//! \~russian
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! If spinlock is unlocked it set to locked state and returns immediate.
|
||||||
//! If spinlock is already locked function blocks until spinlock will be unlocked
|
//! If spinlock is already locked function blocks until spinlock will be unlocked
|
||||||
|
//! \~russian
|
||||||
void lock() {while (flag.test_and_set(std::memory_order_acquire));}
|
void lock() {while (flag.test_and_set(std::memory_order_acquire));}
|
||||||
|
|
||||||
//! \brief Unlock spinlock
|
//! \~english Unlock spinlock
|
||||||
//! \details In any case this function returns immediate
|
//! \~russian
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! In any case this function returns immediate
|
||||||
|
//! \~russian
|
||||||
void unlock() {flag.clear(std::memory_order_release);}
|
void unlock() {flag.clear(std::memory_order_release);}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -57,22 +67,24 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \brief PISpinlockLocker
|
|
||||||
//! \details
|
|
||||||
//! When a PISpinlockLocker object is created, it attempts to lock the spinlock it is given, if "condition" true.
|
|
||||||
//! When control leaves the scope in which the PISpinlockLocker object was created,
|
|
||||||
//! the PISpinlockLocker is destructed and the spinlock is released, if "condition" true.
|
|
||||||
//! If "condition" false this class do nothing.
|
|
||||||
//! The PISpinlockLocker class is non-copyable.
|
|
||||||
class PIP_EXPORT PISpinlockLocker
|
class PIP_EXPORT PISpinlockLocker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NO_COPY_CLASS(PISpinlockLocker)
|
NO_COPY_CLASS(PISpinlockLocker)
|
||||||
|
|
||||||
|
//! \~english Constructs and lock "s" if "condition" is \c true
|
||||||
|
//! \~russian
|
||||||
PISpinlockLocker(PISpinlock & s, bool condition = true): spinlock(s), cond(condition) {if (cond) spinlock.lock();}
|
PISpinlockLocker(PISpinlock & s, bool condition = true): spinlock(s), cond(condition) {if (cond) spinlock.lock();}
|
||||||
|
|
||||||
|
//! \~english Unlock "s" if "condition" was \c true
|
||||||
|
//! \~russian
|
||||||
~PISpinlockLocker() {if (cond) spinlock.unlock();}
|
~PISpinlockLocker() {if (cond) spinlock.unlock();}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PISpinlock & spinlock;
|
PISpinlock & spinlock;
|
||||||
bool cond;
|
bool cond;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PISPINLOCK_H
|
#endif // PISPINLOCK_H
|
||||||
|
|||||||
@@ -54,54 +54,85 @@ __THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_fun
|
|||||||
# define UNREGISTER_THREAD(t)
|
# define UNREGISTER_THREAD(t)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! \class PIThread
|
//! \addtogroup Thread
|
||||||
* \brief Thread class
|
//! \{
|
||||||
* \details This class allow you exec your code in separate thread.
|
//! \class PIThread pithread.h
|
||||||
*
|
//! \~\brief
|
||||||
* \section PIThread_sec0 Synopsis
|
//! \~english Thread class
|
||||||
* Multithreading allow you to write program which will be executed
|
//! \~russian Класс потока
|
||||||
* in several threads simultaneously. This trend allow you to use all
|
//!
|
||||||
* cores of modern processors, but there are many dangers.
|
//! \~\details
|
||||||
*
|
//! \~english
|
||||||
* This class provide virtual functions \a begin(), \a run() and \a end(),
|
//! This class allow you exec your code in separate thread.
|
||||||
* which describes start, execution and finish work of some process.
|
//!
|
||||||
* These functions executes in \b separate thread. When you execute
|
//! \~russian
|
||||||
* \a start(), %PIThread create separate system thread and sequentially
|
//! Этот класс позволяет выполнять код из параллельного потока.
|
||||||
* executes function \a begin(), \a run() and \a end(). You can
|
//!
|
||||||
* reimplement each function and write your own code to execute.
|
//!
|
||||||
* Scheme of functions executing:
|
//! \~english \section PIThread_sec0 Synopsis
|
||||||
\code{.cpp}
|
//! \~russian \section PIThread_sec0 Краткий обзор
|
||||||
begin();
|
//! \~english
|
||||||
event started();
|
//! Multithreading allow you to write program which will be executed
|
||||||
while (isRunning()) {
|
//! in several threads simultaneously. This trend allow you to use all
|
||||||
run();
|
//! cores of modern processors, but there are many dangers.
|
||||||
ThreadFunc();
|
//!
|
||||||
piMSleep(timer_delay);
|
//! This class provide virtual functions \a begin(), \a run() and \a end(),
|
||||||
}
|
//! which describes start, execution and finish work of some process.
|
||||||
event stopped();
|
//! These functions executes in \b separate thread. When you execute
|
||||||
end();
|
//! \a start(), %PIThread create separate system thread and sequentially
|
||||||
\endcode
|
//! executes function \a begin(), \a run() and \a end(). You can
|
||||||
* Unlike from directly using "pthread" or some similar you doesn`t need
|
//! reimplement each function and write your own code to execute.
|
||||||
* to write your own main thread cycle and sleep at every cycle end.
|
//! Scheme of functions executing:
|
||||||
* %PIThread make it for you, and your job is to set sleep value from
|
//!
|
||||||
* contructor or when starting thread, and reimplement \a begin(), \a run()
|
//! \~russian
|
||||||
* and \a end() functions.
|
//!
|
||||||
*
|
//! \~\code{.cpp}
|
||||||
* \section PIThread_sec1 Using without subclassing
|
//! begin();
|
||||||
* You can use %PIThread without subclassing by using "ThreadFunc" pointer
|
//! event started();
|
||||||
* that can be set from constructor or by overloaded function \a start(ThreadFunc func, int timer_delay).
|
//! while (isRunning()) {
|
||||||
* If "func" if not null this function will be executed as \a run(). ThreadFunc is any static
|
//! run();
|
||||||
* function with format void func(void * data). "Data" is custom data set from constructor or
|
//! ThreadFunc();
|
||||||
* with function \a setData(). \n Also you can connect to event \a started(), but
|
//! piMSleep(timer_delay);
|
||||||
* in this case you should to white your thread main cycle, because this event raised only one time.
|
//! }
|
||||||
*
|
//! event stopped();
|
||||||
* \section PIThread_sec2 Locking
|
//! end();
|
||||||
* %PIThread has inrternal mutex that can be locked and unlocked every \a run() if you set this flag
|
//! \endcode
|
||||||
* with function \a needLockRun(bool). Also you can access to this mutex by functions \a lock(), \a unlock()
|
//!
|
||||||
* and \a mutex(). Using this functions together with needLockRun(true) can guarantee one-thread access to
|
//! \~english
|
||||||
* some data.
|
//! Unlike from directly using "pthread" or some similar you doesn`t need
|
||||||
*
|
//! to write your own main thread cycle and sleep at every cycle end.
|
||||||
*/
|
//! %PIThread make it for you, and your job is to set sleep value from
|
||||||
|
//! contructor or when starting thread, and reimplement \a begin(), \a run()
|
||||||
|
//! and \a end() functions.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~english \section PIThread_sec1 Using without subclassing
|
||||||
|
//! \~russian \section PIThread_sec1 Использование без наследования
|
||||||
|
//! \~english
|
||||||
|
//! You can use %PIThread without subclassing by using "ThreadFunc" pointer
|
||||||
|
//! that can be set from constructor or by overloaded function \a start(ThreadFunc func, int timer_delay).
|
||||||
|
//! If "func" if not null this function will be executed as \a run(). ThreadFunc is any static
|
||||||
|
//! function with format void func(void * data). "Data" is custom data set from constructor or
|
||||||
|
//! with function \a setData(). \n Also you can connect to event \a started(), but
|
||||||
|
//! in this case you should to white your thread main cycle, because this event raised only one time.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~english \section PIThread_sec2 Locking
|
||||||
|
//! \~russian \section PIThread_sec2 Блокировки
|
||||||
|
//! \~english
|
||||||
|
//! %PIThread has inrternal mutex that can be locked and unlocked every \a run() if you set this flag
|
||||||
|
//! with function \a needLockRun(bool). Also you can access to this mutex by functions \a lock(), \a unlock()
|
||||||
|
//! and \a mutex(). Using this functions together with needLockRun(true) can guarantee one-thread access to
|
||||||
|
//! some data.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//! \}
|
||||||
|
//!
|
||||||
|
|
||||||
#ifndef MICRO_PIP
|
#ifndef MICRO_PIP
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__;
|
|||||||
|
|
||||||
typedef std::function<void(void *)> ThreadFunc;
|
typedef std::function<void(void *)> ThreadFunc;
|
||||||
|
|
||||||
|
|
||||||
class PIP_EXPORT PIThread: public PIObject
|
class PIP_EXPORT PIThread: public PIObject
|
||||||
{
|
{
|
||||||
PIOBJECT_SUBCLASS(PIThread, PIObject)
|
PIOBJECT_SUBCLASS(PIThread, PIObject)
|
||||||
@@ -74,24 +75,28 @@ class PIP_EXPORT PIThread: public PIObject
|
|||||||
public:
|
public:
|
||||||
NO_COPY_CLASS(PIThread)
|
NO_COPY_CLASS(PIThread)
|
||||||
|
|
||||||
//! Contructs thread with custom data "data", external function "func" and main loop delay "loop_delay".
|
//! \~english Contructs thread with custom data "data", external function "func" and main loop delay "loop_delay"
|
||||||
|
//! \~russian Создает поток с данными "data", функцией "func" и задержкой цикла "loop_delay"
|
||||||
PIThread(void * data, ThreadFunc func, bool startNow = false, int loop_delay = -1);
|
PIThread(void * data, ThreadFunc func, bool startNow = false, int loop_delay = -1);
|
||||||
|
|
||||||
//! Contructs thread with external function "func" and main loop delay "loop_delay".
|
//! \~english Contructs thread with external function "func" and main loop delay "loop_delay"
|
||||||
|
//! \~russian Создает поток с функцией "func" и задержкой цикла "loop_delay"
|
||||||
PIThread(std::function<void()> func, bool startNow = false, int loop_delay = -1);
|
PIThread(std::function<void()> func, bool startNow = false, int loop_delay = -1);
|
||||||
|
|
||||||
//! Contructs thread with main loop delay "loop_delay".
|
//! \~english Contructs thread with main loop delay "loop_delay"
|
||||||
|
//! \~russian Создает поток с задержкой цикла "loop_delay"
|
||||||
PIThread(bool startNow = false, int loop_delay = -1);
|
PIThread(bool startNow = false, int loop_delay = -1);
|
||||||
|
|
||||||
virtual ~PIThread();
|
virtual ~PIThread();
|
||||||
|
|
||||||
//! Priority of thread
|
//! \~english Priority of thread
|
||||||
|
//! \~russian Приоритет потока
|
||||||
enum Priority {
|
enum Priority {
|
||||||
piLowerst /** Lowest */,
|
piLowerst /** \~english Lowest \~russian Низший */ ,
|
||||||
piLow /** Low */,
|
piLow /** \~english Low \~russian Низкий */ ,
|
||||||
piNormal /** Normal, this is default priority of threads and timers */,
|
piNormal /** \~english Normal, this is default priority of threads and timers \~russian Нормальный, это приоритет по умолчанию для потоков и таймеров */ ,
|
||||||
piHigh /** High */,
|
piHigh /** \~english High \~russian Высокий */ ,
|
||||||
piHighest /** Highest */
|
piHighest /** \~english Highest \~russian Высший */
|
||||||
};
|
};
|
||||||
|
|
||||||
EVENT_HANDLER0(bool, start) {return start(-1);}
|
EVENT_HANDLER0(bool, start) {return start(-1);}
|
||||||
@@ -106,27 +111,36 @@ public:
|
|||||||
EVENT_HANDLER1(void, stop, bool, wait);
|
EVENT_HANDLER1(void, stop, bool, wait);
|
||||||
EVENT_HANDLER0(void, terminate);
|
EVENT_HANDLER0(void, terminate);
|
||||||
|
|
||||||
//! \brief Set common data passed to external function
|
//! \~english Set common data passed to external function
|
||||||
|
//! \~russian Устанавливает данные, передаваемые в функцию потока
|
||||||
void setData(void * d) {data_ = d;}
|
void setData(void * d) {data_ = d;}
|
||||||
|
|
||||||
//! \brief Set external function that will be executed after every \a run()
|
//! \~english Set external function that will be executed after every \a run()
|
||||||
|
//! \~russian Устанавливает функцию потока, вызываемую после каждого \a run()
|
||||||
void setSlot(ThreadFunc func) {ret_func = func;}
|
void setSlot(ThreadFunc func) {ret_func = func;}
|
||||||
|
|
||||||
//! \brief Set external function that will be executed after every \a run()
|
//! \~english Set external function that will be executed after every \a run()
|
||||||
|
//! \~russian Устанавливает функцию потока, вызываемую после каждого \a run()
|
||||||
void setSlot(std::function<void()> func) {ret_func = [func](void*){func();};}
|
void setSlot(std::function<void()> func) {ret_func = [func](void*){func();};}
|
||||||
|
|
||||||
//! \brief Set priority of thread
|
//! \~english Set thread priority
|
||||||
|
//! \~russian Устанавливает приоритет потока
|
||||||
void setPriority(PIThread::Priority prior);
|
void setPriority(PIThread::Priority prior);
|
||||||
|
|
||||||
//! \brief Returns common data passed to external function
|
//! \~english Returns common data passed to external function
|
||||||
|
//! \~russian Возвращает данные, передаваемые в функцию потока
|
||||||
void * data() const {return data_;}
|
void * data() const {return data_;}
|
||||||
|
|
||||||
//! \brief Return priority of thread
|
//! \~english Return thread priority
|
||||||
|
//! \~russian Возвращает приоритет потока
|
||||||
PIThread::Priority priority() const {return priority_;}
|
PIThread::Priority priority() const {return priority_;}
|
||||||
|
|
||||||
//! \brief Return \c true if thread is running
|
//! \~english Return if thread is running
|
||||||
|
//! \~russian Возвращает исполняется ли поток
|
||||||
bool isRunning() const {return running_;}
|
bool isRunning() const {return running_;}
|
||||||
|
|
||||||
|
//! \~english Return if thread is stopping
|
||||||
|
//! \~russian Возвращает останавливается ли поток
|
||||||
bool isStopping() const {return running_ && terminating;}
|
bool isStopping() const {return running_ && terminating;}
|
||||||
|
|
||||||
EVENT_HANDLER0(bool, waitForStart) {return waitForStart(-1);}
|
EVENT_HANDLER0(bool, waitForStart) {return waitForStart(-1);}
|
||||||
@@ -134,19 +148,19 @@ public:
|
|||||||
EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);}
|
EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);}
|
||||||
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs);
|
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs);
|
||||||
|
|
||||||
//! \brief Set necessity of lock every \a run with internal mutex
|
//! \~english Set necessity of lock every \a run() with internal mutex
|
||||||
|
//! \~russian Устанавливает необходимость блокировки внутреннего мьютекса каждый \a run()
|
||||||
void needLockRun(bool need) {lockRun = need;}
|
void needLockRun(bool need) {lockRun = need;}
|
||||||
|
|
||||||
//! \brief Lock internal mutex
|
|
||||||
EVENT_HANDLER0(void, lock) const {thread_mutex.lock();}
|
EVENT_HANDLER0(void, lock) const {thread_mutex.lock();}
|
||||||
|
|
||||||
//! \brief Unlock internal mutex
|
|
||||||
EVENT_HANDLER0(void, unlock) const {thread_mutex.unlock();}
|
EVENT_HANDLER0(void, unlock) const {thread_mutex.unlock();}
|
||||||
|
|
||||||
//! \brief Returns internal mutex
|
//! \~english Returns internal mutex
|
||||||
|
//! \~russian Возвращает внутренний мьютекс
|
||||||
PIMutex & mutex() const {return thread_mutex;}
|
PIMutex & mutex() const {return thread_mutex;}
|
||||||
|
|
||||||
//! \brief Returns thread ID
|
//! \~english Returns thread ID
|
||||||
|
//! \~russian Возвращает ID потока
|
||||||
llong tid() const {return tid_;}
|
llong tid() const {return tid_;}
|
||||||
|
|
||||||
void __thread_func__();
|
void __thread_func__();
|
||||||
@@ -155,93 +169,129 @@ public:
|
|||||||
EVENT(started)
|
EVENT(started)
|
||||||
EVENT(stopped)
|
EVENT(stopped)
|
||||||
|
|
||||||
//! \brief Start event handler with name \"handler\" of object \"object\"
|
//! \~english
|
||||||
//! in separate thread with name \"name\"
|
//! Start event handler with name "handler" of object "object"
|
||||||
|
//! in separate thread with name "name"
|
||||||
//! and automatically delete it on function finish
|
//! and automatically delete it on function finish
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
static void runOnce(PIObject * object, const char * handler, const PIString & name = PIString());
|
static void runOnce(PIObject * object, const char * handler, const PIString & name = PIString());
|
||||||
|
|
||||||
//! \brief Start function \"func\" in separate thread with name \"name\"
|
//! \~english
|
||||||
|
//! Start function "func" in separate thread with name "name"
|
||||||
//! and automatically delete it on function finish
|
//! and automatically delete it on function finish
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
static void runOnce(std::function<void()> func, const PIString & name = PIString());
|
static void runOnce(std::function<void()> func, const PIString & name = PIString());
|
||||||
|
|
||||||
//! \handlers
|
//! \handlers
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
/** \fn bool start(int timer_delay = -1)
|
//! \fn bool start(int timer_delay = -1)
|
||||||
* \brief Start thread
|
//! \~english Start thread
|
||||||
* \details Start execution of \a run() in internal loop with
|
//! \~russian Запускает поток
|
||||||
* "timer_delay" delay in milliseconds. If "timer_delay" <= 0
|
//! \~\details
|
||||||
* there is no delay in loop. Thread also exec external function
|
//! \~english
|
||||||
* set by \a setSlot() if it`s not null
|
//! Start execution of \a run() in internal loop with
|
||||||
*
|
//! "timer_delay" delay in milliseconds. If "timer_delay" <= 0
|
||||||
* \return \c false if thread already started or can`t start thread */
|
//! there is no delay in loop. Thread also exec external function
|
||||||
|
//! set by \a setSlot() if it`s not null
|
||||||
|
//! \return \c false if thread already started or can`t start thread
|
||||||
|
//! \~russian
|
||||||
|
|
||||||
/** \fn bool startOnce()
|
//! \fn bool startOnce()
|
||||||
* \brief Start thread without internal loop
|
//! \~english Start thread without internal loop
|
||||||
* \details Start execution of \a run() once. Thread also exec
|
//! \~russian Запускает поток без внутреннего цикла
|
||||||
* external function set by \a setSlot() if it`s not null
|
//! \~\details
|
||||||
*
|
//! \~english
|
||||||
* \return \c false if thread already started or can`t start thread */
|
//! Start execution of \a run() once. Thread also exec
|
||||||
|
//! external function set by \a setSlot() if it`s not null
|
||||||
|
//! \return \c false if thread already started or can`t start thread
|
||||||
|
//! \~russian
|
||||||
|
|
||||||
/** \fn bool startOnce(ThreadFunc func)
|
//! \fn bool startOnce(ThreadFunc func)
|
||||||
* \brief Start thread without internal loop
|
//! \~english Start thread without internal loop
|
||||||
* \details Overloaded function. Set external function "func" before start
|
//! \~russian Запускает поток без внутреннего цикла
|
||||||
*
|
//! \~\details
|
||||||
* \return \c false if thread already started or can`t start thread */
|
//! \~english
|
||||||
|
//! Overloaded function. Set external function "func" before start
|
||||||
|
//! \return \c false if thread already started or can`t start thread
|
||||||
|
//! \~russian
|
||||||
|
|
||||||
/** \fn void stop(bool wait = false)
|
//! \fn void stop(bool wait = false)
|
||||||
* \brief Stop thread
|
//! \~english Stop thread
|
||||||
* \details Stop execution of thread and wait for it finish
|
//! \~russian Останавливает поток
|
||||||
* if "wait" is \c true. This function can block for infinite
|
//! \~\details
|
||||||
* time if "wait" is \c true and any of thread function is
|
//! \~english
|
||||||
* busy forever */
|
//! Stop execution of thread and wait for it finish
|
||||||
|
//! if "wait" is \c true. This function can block for infinite
|
||||||
|
//! time if "wait" is \c true and any of thread function is
|
||||||
|
//! busy forever
|
||||||
|
//! \~russian
|
||||||
|
|
||||||
/** \fn void terminate()
|
//! \fn void terminate()
|
||||||
* \brief Strongly stop thread
|
//! \~english Strongly stop thread
|
||||||
* \details Stop execution of thread immediately */
|
//! \~russian Жестко останавливает поток
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! Stop execution of thread immediately
|
||||||
|
//! \~russian
|
||||||
|
|
||||||
/** \fn bool waitForStart(int timeout_msecs = -1)
|
//! \fn bool waitForStart(int timeout_msecs = -1)
|
||||||
* \brief Wait for thread start
|
//! \~english Wait for thread start
|
||||||
* \details This function block until thread start for "timeout_msecs"
|
//! \~russian Ожидает старта потока
|
||||||
* or forever if "timeout_msecs" < 0
|
//! \~\details
|
||||||
*
|
//! \~english
|
||||||
* \return \c false if timeout is exceeded */
|
//! This function block until thread start for "timeout_msecs"
|
||||||
|
//! or forever if "timeout_msecs" < 0
|
||||||
|
//! \return \c false if timeout is exceeded
|
||||||
|
//! \~russian
|
||||||
|
|
||||||
/** \fn bool waitForFinish(int timeout_msecs = -1)
|
//! \fn bool waitForFinish(int timeout_msecs = -1)
|
||||||
* \brief Wait for thread finish
|
//! \~english Wait for thread finish
|
||||||
* \details This function block until thread finish for "timeout_msecs"
|
//! \~russian Ожидает завершения потока
|
||||||
* or forever if "timeout_msecs" < 0
|
//! \~\details
|
||||||
*
|
//! \~english
|
||||||
* \return \c false if timeout is exceeded */
|
//! This function block until thread finish for "timeout_msecs"
|
||||||
|
//! or forever if "timeout_msecs" < 0
|
||||||
|
//! \return \c false if timeout is exceeded
|
||||||
|
//! \~russian
|
||||||
|
|
||||||
//! \fn void lock()
|
//! \fn void lock()
|
||||||
//! \brief Lock internal mutex
|
//! \~english Lock internal mutex
|
||||||
|
//! \~russian Блокирует внутренний мьютекс
|
||||||
|
|
||||||
//! \fn void unlock()
|
//! \fn void unlock()
|
||||||
//! \brief Unlock internal mutex
|
//! \~english Unlock internal mutex
|
||||||
|
//! \~russian Разблокирует внутренний мьютекс
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
//! \events
|
//! \events
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! \fn void started()
|
//! \fn void started()
|
||||||
//! \brief Raise on thread start
|
//! \~english Raise on thread start
|
||||||
|
//! \~russian Вызывается при старте потока
|
||||||
|
|
||||||
//! \fn void stopped()
|
//! \fn void stopped()
|
||||||
//! \brief Raise on thread stop
|
//! \~english Raise on thread stop
|
||||||
|
//! \~russian Вызывается при завершении потока
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static int priority2System(PIThread::Priority p);
|
static int priority2System(PIThread::Priority p);
|
||||||
|
|
||||||
//! Function executed once at the start of thread.
|
//! \~english Function executed once at the start of thread
|
||||||
|
//! \~russian Метод выполняется один раз при старте потока
|
||||||
virtual void begin() {;}
|
virtual void begin() {;}
|
||||||
|
|
||||||
//! Function executed at every "timer_delay" msecs until thread was stopped.
|
//! \~english Function executed at every "timer_delay" msecs until thread was stopped
|
||||||
|
//! \~russian Метод выполняется каждые "timer_delay" миллисекунд
|
||||||
virtual void run() {;}
|
virtual void run() {;}
|
||||||
|
|
||||||
//! Function executed once at the end of thread.
|
//! \~english Function executed once at the end of thread
|
||||||
|
//! \~russian Метод выполняется один раз при остановке потока
|
||||||
virtual void end() {;}
|
virtual void end() {;}
|
||||||
|
|
||||||
std::atomic_bool terminating, running_, lockRun;
|
std::atomic_bool terminating, running_, lockRun;
|
||||||
|
|||||||
@@ -19,10 +19,50 @@
|
|||||||
|
|
||||||
#include "pithreadnotifier.h"
|
#include "pithreadnotifier.h"
|
||||||
|
|
||||||
|
//! \addtogroup Thread
|
||||||
|
//! \{
|
||||||
|
//! \class PIThreadNotifier pithreadnotifier.h
|
||||||
|
//!
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Class for simple notify and wait in different threads
|
||||||
|
//! \~russian Класс для простого уведомления и ожидания в различных потоках
|
||||||
|
//!
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~english \section PIThreadNotifier_sec0 Synopsis
|
||||||
|
//! \~russian \section PIThreadNotifier_sec0 Краткий обзор
|
||||||
|
//! \~english
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~english \section PIThreadNotifier_sec1 Usage
|
||||||
|
//! \~russian \section PIThreadNotifier_sec1 Использование
|
||||||
|
//! \~english
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
|
||||||
PIThreadNotifier::PIThreadNotifier() : cnt(0) {}
|
PIThreadNotifier::PIThreadNotifier() : cnt(0) {}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! If \a notifyOnce() has been called before, then returns immediately.
|
||||||
|
//! If \a notifyOnce() has been called "n" times, then returns immediately "n" times,
|
||||||
|
//! but only if wait in one thread.
|
||||||
|
//! If many threads waiting, then if \a notifyOnce() has been called "n" times,
|
||||||
|
//! all threads total returns "n" times in random sequence.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//!
|
||||||
void PIThreadNotifier::wait() {
|
void PIThreadNotifier::wait() {
|
||||||
m.lock();
|
m.lock();
|
||||||
while (cnt == 0) v.wait(m);
|
while (cnt == 0) v.wait(m);
|
||||||
@@ -31,6 +71,12 @@ void PIThreadNotifier::wait() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! If many threads waiting, then notify randomly one.
|
||||||
|
//! If call this "n" times, then notify any waiting threads totally "n" times.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
void PIThreadNotifier::notifyOnce() {
|
void PIThreadNotifier::notifyOnce() {
|
||||||
m.lock();
|
m.lock();
|
||||||
cnt++;
|
cnt++;
|
||||||
|
|||||||
@@ -33,17 +33,12 @@ class PIP_EXPORT PIThreadNotifier {
|
|||||||
public:
|
public:
|
||||||
PIThreadNotifier();
|
PIThreadNotifier();
|
||||||
|
|
||||||
//! Start waiting, return if other thread call \a notifyOnce().
|
//! \~english Start waiting, return if other thread call \a notifyOnce()
|
||||||
//! If \a notifyOnce() has been called before, then returns immediately.
|
//! \~russian Начать ожидание, продолжает когда другой поток вызовет \a notifyOnce()
|
||||||
//! If notifyOnce() has been called "n" times, then returns immediately "n" times,
|
|
||||||
//! but only if wait in one thread.
|
|
||||||
//! If many threads waiting, then If notifyOnce() has been called "n" times,
|
|
||||||
//! All threads total returns "n" times in random sequence.
|
|
||||||
void wait();
|
void wait();
|
||||||
|
|
||||||
//! Notify one waiting thread, wich waiting on \a wait() function.
|
//! \~english Notify one waiting thread, which waiting on \a wait() function
|
||||||
//! If many threads waiting, then notify randomly one.
|
//! \~russian Уведомить один из ожидающих потоков, которые висят на методе \a wait()
|
||||||
//! If call this "n" times, then notify any waiting threads totally "n" times.
|
|
||||||
void notifyOnce();
|
void notifyOnce();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -22,51 +22,82 @@
|
|||||||
#include "pithread.h"
|
#include "pithread.h"
|
||||||
|
|
||||||
|
|
||||||
/*! \class PIThreadPoolLoop
|
//! \addtogroup Thread
|
||||||
* \brief Thread class
|
//! \{
|
||||||
* \details This class allow you parallelize loop.
|
//! \class PIThreadPoolLoop pithreadpoolloop.h
|
||||||
*
|
//! \~english Thread pool loop
|
||||||
* \section PIThreadPoolLoop_sec0 Usage
|
//! \~russian Пул потоков
|
||||||
* This class designed to replace "for(;;)" statement in very simple way.
|
//!
|
||||||
* In constructor several threads created, then by "setFunction()" method
|
//! \~\details
|
||||||
* you should pass body of your loop, and then call "start()" or "exec()".
|
//! \~english
|
||||||
* Every thread take loop counter and execute your function until all
|
//! This class allow you parallelize loop.
|
||||||
* counter range is passed.
|
//!
|
||||||
*
|
//! \~russian
|
||||||
* Example:
|
//! Этот класс позволяет распараллелить цикл
|
||||||
\code{.cpp}
|
//!
|
||||||
PIVector<int> data(10, [](int i)->int{return i;});
|
//!
|
||||||
|
//! \~english \section PIThreadPoolLoop_sec0 Usage
|
||||||
piCout << data; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
//! \~russian \section PIThreadPoolLoop_sec0 Использование
|
||||||
|
//! \~english
|
||||||
PIThreadPoolLoop pool;
|
//! This class designed to parallel "for(;;)" statement in very simple way.
|
||||||
pool.exec(0, data.size(), [&](int i){ // parallel analogue "for (int i = 0; i < data.size(); i++)"
|
//! In constructor several threads created, then by \a setFunction() method
|
||||||
data[i] = data[i] + 10;
|
//! you should pass body of your loop, and then call \a start() or \a exec().
|
||||||
});
|
//! Every thread take loop counter and execute your function until all
|
||||||
|
//! counter range is passed.
|
||||||
piCout << data; // {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
|
//!
|
||||||
\endcode
|
//! Example:
|
||||||
*
|
//! \~russian
|
||||||
* Equivalent to:
|
//! Этот класс предназначен для распараллеливания цикла "for(;;)" максимально простым способом.
|
||||||
\code{.cpp}
|
//! В конструкторе создается несколько потоков, затем методом \a setFunction()
|
||||||
PIVector<int> data(10, [](int i)->int{return i;});
|
//! устанавливается функция, представляющая собой тело цикла. Затем вызовом
|
||||||
|
//! \a start() или \a exec() цикл исполняется параллельно. Каждый поток получает
|
||||||
piCout << data; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
//! значение переменной цикла и вызывает функцию-тело до тех пор, пока
|
||||||
|
//! весь диапазон не будет исполнен.
|
||||||
pool.setFunction([&](int i){
|
//!
|
||||||
data[i] = data[i] + 10;
|
//! Пример:
|
||||||
});
|
//!
|
||||||
pool.exec(0, data.size());
|
//! \~\code{.cpp}
|
||||||
|
//! PIVector<int> data(10, [](int i)->int{return i;});
|
||||||
piCout << data; // {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
|
//!
|
||||||
\endcode
|
//! piCout << data; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||||
*
|
//!
|
||||||
* \section PIThreadPoolLoop_sec1 Important
|
//! PIThreadPoolLoop pool;
|
||||||
* Due to multithreading it`s very important to protect output data of loop body, use mutex.
|
//! pool.exec(0, data.size(), [&](int i){ // parallel analogue "for (int i = 0; i < data.size(); i++)"
|
||||||
* Also remember that execution order is undefined and you shouldn`t use global variables in
|
//! data[i] = data[i] + 10;
|
||||||
* your function. Use local variables and lambda capture.
|
//! });
|
||||||
*
|
//!
|
||||||
*/
|
//! piCout << data; // {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
|
||||||
|
//! \endcode
|
||||||
|
//!
|
||||||
|
//! \~english Equivalent to:
|
||||||
|
//! \~russian Эквивалентно:
|
||||||
|
//! \~\code{.cpp}
|
||||||
|
//! PIVector<int> data(10, [](int i)->int{return i;});
|
||||||
|
//!
|
||||||
|
//! piCout << data; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||||
|
//!
|
||||||
|
//! pool.setFunction([&](int i){
|
||||||
|
//! data[i] = data[i] + 10;
|
||||||
|
//! });
|
||||||
|
//! pool.exec(0, data.size());
|
||||||
|
//!
|
||||||
|
//! piCout << data; // {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
|
||||||
|
//! \endcode
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~english \section PIThreadPoolLoop_sec1 Important
|
||||||
|
//! \~russian \section PIThreadPoolLoop_sec1 Важно
|
||||||
|
//! \~english
|
||||||
|
//! Due to multithreading it`s very important to protect output data of loop body, use mutex.
|
||||||
|
//! Also remember that execution order is undefined and you shouldn`t use global variables in
|
||||||
|
//! your function. Use local variables and lambda capture.
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//! В силу многопоточности очень важно защитить выходные данные тела цикла с помощью блокировок (мьютекса).
|
||||||
|
//! Также стоит помнить, что последовательность выполнения неопределена, и не стоит использовать глобальных
|
||||||
|
//! переменных в теле цикла. Используйте локальные переменные и захват в лямбде.
|
||||||
|
//!
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
|
||||||
PIThreadPoolLoop::PIThreadPoolLoop(int thread_cnt) {
|
PIThreadPoolLoop::PIThreadPoolLoop(int thread_cnt) {
|
||||||
|
|||||||
@@ -33,30 +33,50 @@ class PIThread;
|
|||||||
class PIP_EXPORT PIThreadPoolLoop {
|
class PIP_EXPORT PIThreadPoolLoop {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//! \~english
|
||||||
//! Contructs thread pool with threads count "thread_cnt".
|
//! Contructs thread pool with threads count "thread_cnt".
|
||||||
//! If "thread_cnt" = -1 then system processors count used
|
//! If "thread_cnt" = -1 then system processors count used
|
||||||
|
//! \~russian
|
||||||
|
//! Создает пул из "thread_cnt" потоков. Если "thread_cnt" = -1
|
||||||
|
//! то используется количество процессоров системы
|
||||||
PIThreadPoolLoop(int thread_cnt = -1);
|
PIThreadPoolLoop(int thread_cnt = -1);
|
||||||
|
|
||||||
virtual ~PIThreadPoolLoop();
|
virtual ~PIThreadPoolLoop();
|
||||||
|
|
||||||
//! Set threads function to "f" with format [](int){...}
|
//! \~english Set threads function to "f" with format [ ](int){ ... }
|
||||||
|
//! \~russian Устанавливает функцию потоков на "f" в формате [ ](int){ ... }
|
||||||
void setFunction(std::function<void(int)> f);
|
void setFunction(std::function<void(int)> f);
|
||||||
|
|
||||||
//! Wait for all threads stop
|
//! \~english Wait for all threads stop
|
||||||
|
//! \~russian Ожидает завершения всех потоков
|
||||||
void wait();
|
void wait();
|
||||||
|
|
||||||
|
//! \~english
|
||||||
//! Start functions execution with integer argument range
|
//! Start functions execution with integer argument range
|
||||||
//! from "index_start" to "index_start + index_count - 1"
|
//! from "index_start" to "index_start + index_count - 1"
|
||||||
|
//! \~russian
|
||||||
|
//! Начинает исполнение потоков с аргументами по диапазону
|
||||||
|
//! от "index_start" до "index_start + index_count - 1"
|
||||||
void start(int index_start, int index_count);
|
void start(int index_start, int index_count);
|
||||||
|
|
||||||
|
//! \~english
|
||||||
//! Start functions execution with integer argument range
|
//! Start functions execution with integer argument range
|
||||||
//! from "index_start" to "index_start + index_count - 1"
|
//! from "index_start" to "index_start + index_count - 1"
|
||||||
//! and wait for finish
|
//! and wait for finish
|
||||||
|
//! \~russian
|
||||||
|
//! Начинает исполнение потоков с аргументами по диапазону
|
||||||
|
//! от "index_start" до "index_start + index_count - 1"
|
||||||
|
//! и ожидает завершения
|
||||||
void exec(int index_start, int index_count);
|
void exec(int index_start, int index_count);
|
||||||
|
|
||||||
|
//! \~english
|
||||||
//! Start functions "f" execution with integer argument range
|
//! Start functions "f" execution with integer argument range
|
||||||
//! from "index_start" to "index_start + index_count - 1"
|
//! from "index_start" to "index_start + index_count - 1"
|
||||||
//! and wait for finish
|
//! and wait for finish
|
||||||
|
//! \~russian
|
||||||
|
//! Начинает исполнение потоками функции "f" с аргументами по диапазону
|
||||||
|
//! от "index_start" до "index_start + index_count - 1"
|
||||||
|
//! и ожидает завершения
|
||||||
void exec(int index_start, int index_count, std::function<void(int)> f);
|
void exec(int index_start, int index_count, std::function<void(int)> f);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -24,31 +24,94 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*! \class PITimer
|
//! \addtogroup Thread
|
||||||
* \brief Timer
|
//! \{
|
||||||
*
|
//! \class PITimer pitimer.h
|
||||||
* \section PITimer_sec0 Synopsis
|
//!
|
||||||
* This class implements timer function. PIP timers supports 3 way to tick notify,
|
//! \~\brief
|
||||||
* frequency delimiters and time measurements.
|
//! \~english Timer
|
||||||
* \section PITimer_sec1 Notify variants
|
//! \~russian Таймер
|
||||||
* Notify variants:
|
//!
|
||||||
* * "slot" - static function with format void func(void * data, int delimiter);
|
//! \~\details
|
||||||
* * event - \a tickEvent();
|
//!
|
||||||
* * virtual function - \a tick().
|
//! \~english \section PITimer_sec0 Synopsis
|
||||||
*
|
//! \~russian \section PITimer_sec0 Краткий обзор
|
||||||
* All these variants are equivalent, use most applicable.
|
//! \~english
|
||||||
* \section PITimer_sec2 Frequency delimiters
|
//! This class implements timer function. PIP timers supports 3 way to tick notify,
|
||||||
* Frequency delimiter is an integer number and "slot" function. If "slot" function is null
|
//! deferred start and frequency delimiters.
|
||||||
* timer main "slot" will be used. Each delimiter numbers tick timer will be execute
|
//!
|
||||||
* delimiters or timer main "slot" function with \b delimiter value = delimiter number.
|
//! \~russian
|
||||||
* Example: \snippet pitimer.cpp delimiter
|
//! Этот класс реализует таймер. Таймер PIP поддерживает 3 варианта уведомления,
|
||||||
* \section PITimer_sec3 Time measurements
|
//! отложенный старт и делители частоты.
|
||||||
* PITimer can be used as time measurer. Function \a reset() set time mark to current
|
//!
|
||||||
* system time, then functions double elapsed_*() returns time elapsed from this mark.
|
//!
|
||||||
* These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m"
|
//! \~english \section PITimer_sec1 Notify variants
|
||||||
* and "s"
|
//! \~russian \section PITimer_sec1 Варианты уведомления
|
||||||
* Example: \snippet pitimer.cpp elapsed
|
//! \~english
|
||||||
*/
|
//! Notify variants:
|
||||||
|
//! * "slot" - static function with format void func(void * data, int delimiter) or lambda-function;
|
||||||
|
//! * event - \a tickEvent();
|
||||||
|
//! * virtual function - \a tick().
|
||||||
|
//!
|
||||||
|
//! Lambda should be [ ]( ){ } or [ ](void*){ } format.
|
||||||
|
//!
|
||||||
|
//! All these variants are equivalent, use most applicable.
|
||||||
|
//! \~russian
|
||||||
|
//! Варианты уведомления:
|
||||||
|
//! * "slot" - статический метод в формате void func(void * data, int delimiter) или лямбда-функция;
|
||||||
|
//! * event - \a tickEvent();
|
||||||
|
//! * виртуальный метод - \a tick().
|
||||||
|
//!
|
||||||
|
//! Лямбда-функция должна быть в формате [ ]( ){ } или [ ](void*){ }.
|
||||||
|
//!
|
||||||
|
//! Все варианты аналогичны друг другу, используйте самый удобный.
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! \~english \section PITimer_sec2 Frequency delimiters
|
||||||
|
//! \~russian \section PITimer_sec2 Делители частоты
|
||||||
|
//! \~english
|
||||||
|
//! Frequency delimiter is an integer number and "slot" function. If "slot" function is null
|
||||||
|
//! timer main "slot" will be used. Each delimiter numbers tick timer will be execute
|
||||||
|
//! delimiters or timer main "slot" function with \b delimiter value = delimiter number.
|
||||||
|
//!
|
||||||
|
//! Example:
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//! Делитель частоты это целое число и необязательный метод "slot". Если метод не указан,
|
||||||
|
//! то будет использован основной "slot". Каждые \b delimiter тиков будет дополнительно вызван
|
||||||
|
//! "slot" делителя либо основной "slot" с аргументом \b delimiter равным значению делителя.
|
||||||
|
//!
|
||||||
|
//! Пример:
|
||||||
|
//!
|
||||||
|
//! \~\code
|
||||||
|
//! void tfunc(void * , int delim) {
|
||||||
|
//! piCout << "tick with delimiter" << delim;
|
||||||
|
//! };
|
||||||
|
//! void tfunc4(void * , int delim) {
|
||||||
|
//! piCout << "tick4 with delimiter" << delim;
|
||||||
|
//! };
|
||||||
|
//! int main() {
|
||||||
|
//! PITimer timer(tfunc);
|
||||||
|
//! timer.addDelimiter(2);
|
||||||
|
//! timer.addDelimiter(4, tfunc4);
|
||||||
|
//! timer.start(50);
|
||||||
|
//! piMSleep(200);
|
||||||
|
//! timer.stop();
|
||||||
|
//! timer.waitForFinish();
|
||||||
|
//! return 0;
|
||||||
|
//! };
|
||||||
|
//! /* Result:
|
||||||
|
//! tick with delimiter 1
|
||||||
|
//! tick with delimiter 1
|
||||||
|
//! tick with delimiter 2
|
||||||
|
//! tick with delimiter 1
|
||||||
|
//! tick with delimiter 1
|
||||||
|
//! tick with delimiter 2
|
||||||
|
//! tick4 with delimiter 4
|
||||||
|
//! */
|
||||||
|
//! \endcode
|
||||||
|
//!
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
|
||||||
_PITimerBase::_PITimerBase() {
|
_PITimerBase::_PITimerBase() {
|
||||||
@@ -603,23 +666,43 @@ bool PITimer::start(int interval_ms_i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! Timer wait "delay_msecs" milliseconds and then normally starts with \a interval() loop delay
|
||||||
|
//! \~russian
|
||||||
|
//! Таймер ожидает "delay_msecs" миллисекунд, а затем стартует с интервалом \a interval()
|
||||||
void PITimer::startDeferred(double delay_ms) {
|
void PITimer::startDeferred(double delay_ms) {
|
||||||
init();
|
init();
|
||||||
imp->startDeferred(delay_ms);
|
imp->startDeferred(delay_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! Timer wait "delay_msecs" milliseconds and then normally starts with "interval_msecs" loop delay
|
||||||
|
//! \~russian
|
||||||
|
//! Таймер ожидает "delay_msecs" миллисекунд, а затем стартует с интервалом "interval_msecs"
|
||||||
void PITimer::startDeferred(double interval_ms, double delay_ms) {
|
void PITimer::startDeferred(double interval_ms, double delay_ms) {
|
||||||
init();
|
init();
|
||||||
imp->startDeferred(interval_ms, delay_ms);
|
imp->startDeferred(interval_ms, delay_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! Timer wait until "start_datetime" and then normally starts with \a interval() loop delay
|
||||||
|
//! \~russian
|
||||||
|
//! Таймер ожидает наступления "start_datetime", а затем стартует с интервалом \a interval()
|
||||||
void PITimer::startDeferred(PIDateTime start_datetime) {
|
void PITimer::startDeferred(PIDateTime start_datetime) {
|
||||||
startDeferred(imp->interval_, start_datetime);
|
startDeferred(imp->interval_, start_datetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! Timer wait until "start_datetime" and then normally starts with "interval_msecs" loop delay
|
||||||
|
//! \~russian
|
||||||
|
//! Таймер ожидает наступления "start_datetime", а затем стартует с интервалом "interval_msecs"
|
||||||
void PITimer::startDeferred(double interval_ms, PIDateTime start_datetime) {
|
void PITimer::startDeferred(double interval_ms, PIDateTime start_datetime) {
|
||||||
init();
|
init();
|
||||||
imp->startDeferred(interval_ms, start_datetime);
|
imp->startDeferred(interval_ms, start_datetime);
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ public:
|
|||||||
double interval() const {return interval_;}
|
double interval() const {return interval_;}
|
||||||
void setInterval(double i);
|
void setInterval(double i);
|
||||||
|
|
||||||
//! \brief Return \c true if thread is running
|
|
||||||
bool isRunning() const {return running_;}
|
bool isRunning() const {return running_;}
|
||||||
|
|
||||||
bool isStopped() const {return !running_;}
|
bool isStopped() const {return !running_;}
|
||||||
@@ -79,45 +78,64 @@ class PIP_EXPORT PITimer: public PIObject {
|
|||||||
public:
|
public:
|
||||||
NO_COPY_CLASS(PITimer)
|
NO_COPY_CLASS(PITimer)
|
||||||
|
|
||||||
//! \brief Constructs timer with PITimer::Thread implementation
|
//! \~english Constructs timer with PITimer::Thread implementation
|
||||||
|
//! \~russian Создает таймер с реализацией PITimer::Thread
|
||||||
explicit PITimer();
|
explicit PITimer();
|
||||||
|
|
||||||
//! \brief Timer implementations
|
//! \~english Timer implementations
|
||||||
|
//! \~russian Реализация таймера
|
||||||
enum TimerImplementation {
|
enum TimerImplementation {
|
||||||
Thread /*! Timer works in his own thread. Intervals are measured by the system time */ = 0x01,
|
Thread /*!
|
||||||
ThreadRT /*! Using POSIX timer with SIGEV_THREAD notification. \attention Doesn`t support on Windows and Mac OS! */ = 0x02,
|
\~english Timer works in his own thread. Intervals are measured by the system time
|
||||||
Pool /*! Using single TimerPool for all timers with this implementation. TimerPool works as Thread implementation and
|
\~russian Таймер работает в собственном потоке. Интервалы измеряются с помощью системного времени
|
||||||
* sequentially executes all timers. \attention Use this implementation with care! */ = 0x04
|
*/ = 0x01,
|
||||||
|
ThreadRT /*!
|
||||||
|
\~english Using POSIX timer with SIGEV_THREAD notification. \attention Doesn`t support on Windows and Mac OS!
|
||||||
|
\~russian Использовать таймер POSIX с SIGEV_THREAD уведомлением. \attention Не поддерживается на Windows и Mac OS!
|
||||||
|
*/ = 0x02,
|
||||||
|
Pool /*!
|
||||||
|
\~english Using single TimerPool for all timers with this implementation. TimerPool works as Thread implementation and
|
||||||
|
sequentially executes all timers. \attention Use this implementation with care!
|
||||||
|
\~russian Использовать единый TimerPool для всех таймеров с этой реализацией. TimerPool реализован через Thread и
|
||||||
|
последовательно исполняет все таймеры. \attention Осторожнее с этой реализацией!
|
||||||
|
*/ = 0x04
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief Constructs timer with "ti" implementation
|
//! \~english Constructs timer with "ti" implementation
|
||||||
|
//! \~russian Создает таймер с реализацией "ti"
|
||||||
explicit PITimer(TimerImplementation ti);
|
explicit PITimer(TimerImplementation ti);
|
||||||
|
|
||||||
//! \brief Constructs timer with "slot" slot void(void *,int), "data" data and "ti" implementation
|
//! \~english Constructs timer with "slot" slot void(void *,int), "data" data and "ti" implementation
|
||||||
|
//! \~russian Создает таймер со слотом "slot", данными "data" и реализацией "ti"
|
||||||
explicit PITimer(TimerEvent slot, void * data = 0, TimerImplementation ti = Thread);
|
explicit PITimer(TimerEvent slot, void * data = 0, TimerImplementation ti = Thread);
|
||||||
|
|
||||||
//! \brief Constructs timer with "slot" slot void(), and "ti" implementation
|
//! \~english Constructs timer with "slot" slot void(), and "ti" implementation
|
||||||
|
//! \~russian Создает таймер со слотом "slot" и реализацией "ti"
|
||||||
explicit PITimer(std::function<void ()> slot, TimerImplementation ti = Thread);
|
explicit PITimer(std::function<void ()> slot, TimerImplementation ti = Thread);
|
||||||
|
|
||||||
//! \brief Constructs timer with "slot" slot void(void *), "data" data and "ti" implementation
|
//! \~english Constructs timer with "slot" slot void(void *), "data" data and "ti" implementation
|
||||||
|
//! \~russian Создает таймер со слотом "slot", данными "data" и реализацией "ti"
|
||||||
explicit PITimer(std::function<void (void *)> slot, void * data, TimerImplementation ti = Thread);
|
explicit PITimer(std::function<void (void *)> slot, void * data, TimerImplementation ti = Thread);
|
||||||
|
|
||||||
virtual ~PITimer();
|
virtual ~PITimer();
|
||||||
|
|
||||||
|
|
||||||
//! \brief Returns timer implementation
|
//! \~english Returns timer implementation
|
||||||
|
//! \~russian Возвращает реализацию таймера
|
||||||
PITimer::TimerImplementation implementation() const {return imp_mode;}
|
PITimer::TimerImplementation implementation() const {return imp_mode;}
|
||||||
|
|
||||||
//! \brief Returns timer loop delay in milliseconds
|
//! \~english Returns timer loop delay in milliseconds
|
||||||
|
//! \~russian Возвращает задержку цикла таймера в миллисекундах
|
||||||
double interval() const;
|
double interval() const;
|
||||||
|
|
||||||
//! \brief Set timer loop delay in milliseconds
|
|
||||||
EVENT_HANDLER1(void, setInterval, double, ms);
|
EVENT_HANDLER1(void, setInterval, double, ms);
|
||||||
|
|
||||||
//! \brief Returns if timer is started
|
//! \~english Returns if timer is started
|
||||||
|
//! \~russian Возвращает работает ли таймер
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
|
||||||
//! \brief Returns if timer is not started
|
//! \~english Returns if timer is not started
|
||||||
|
//! \~russian Возвращает остановлен ли таймер
|
||||||
bool isStopped() const;
|
bool isStopped() const;
|
||||||
|
|
||||||
EVENT_HANDLER0(bool, start);
|
EVENT_HANDLER0(bool, start);
|
||||||
@@ -126,24 +144,20 @@ public:
|
|||||||
EVENT_HANDLER0(bool, restart);
|
EVENT_HANDLER0(bool, restart);
|
||||||
|
|
||||||
|
|
||||||
/** \brief Start timer with \b interval() loop delay after \b delay_msecs delay.
|
//! \~english Start timer with \a interval() loop delay after "delay_msecs" delay
|
||||||
* \details Timer wait \b delay_msecs milliseconds and then normally starts with
|
//! \~russian Запускает таймер с интервалом \a interval() после ожидания "delay_msecs"
|
||||||
* \b interval() loop delay. */
|
|
||||||
void startDeferred(double delay_ms);
|
void startDeferred(double delay_ms);
|
||||||
|
|
||||||
/** \brief Start timer with \b interval_msecs loop delay after \b delay_msecs delay.
|
//! \~english Start timer with "interval_msecs" loop delay after "delay_msecs" delay
|
||||||
* \details Timer wait \b delay_msecs milliseconds and then normally starts with
|
//! \~russian Запускает таймер с интервалом "interval_msecs" после ожидания "delay_msecs"
|
||||||
* \b interval_msecs loop delay. */
|
|
||||||
void startDeferred(double interval_ms, double delay_ms);
|
void startDeferred(double interval_ms, double delay_ms);
|
||||||
|
|
||||||
/** \brief Start timer with \b interval() loop delay after \b start_datetime date and time.
|
//! \~english Start timer with \a interval() loop delay after "start_datetime" date and time
|
||||||
* \details Timer wait until \b start_datetime and then normally starts with
|
//! \~russian Запускает таймер с интервалом \a interval() после наступления "start_datetime"
|
||||||
* \b interval() loop delay. */
|
|
||||||
void startDeferred(PIDateTime start_datetime);
|
void startDeferred(PIDateTime start_datetime);
|
||||||
|
|
||||||
/** \brief Start timer with \b interval_msecs loop delay after \b start_datetime date and time.
|
//! \~english Start timer with "interval_msecs" loop delay after "start_datetime" date and time
|
||||||
* \details Timer wait until \b start_datetime and then normally starts with
|
//! \~russian Запускает таймер с интервалом "interval_msecs" после наступления "start_datetime"
|
||||||
* \b interval_msecs loop delay. */
|
|
||||||
void startDeferred(double interval_ms, PIDateTime start_datetime);
|
void startDeferred(double interval_ms, PIDateTime start_datetime);
|
||||||
|
|
||||||
EVENT_HANDLER0(bool, stop);
|
EVENT_HANDLER0(bool, stop);
|
||||||
@@ -151,43 +165,52 @@ public:
|
|||||||
bool waitForFinish() {return waitForFinish(-1);}
|
bool waitForFinish() {return waitForFinish(-1);}
|
||||||
bool waitForFinish(int timeout_msecs);
|
bool waitForFinish(int timeout_msecs);
|
||||||
|
|
||||||
//! \brief Set custom data
|
//! \~english Set custom data
|
||||||
|
//! \~russian Установить данные, передаваемые в метод таймера
|
||||||
void setData(void * data_) {data_t = data_;}
|
void setData(void * data_) {data_t = data_;}
|
||||||
|
|
||||||
//! \brief Set timer tick function
|
//! \~english Returns common data passed to tick functions
|
||||||
|
//! \~russian Возвращает данные, передаваемые в метод таймера
|
||||||
|
void * data() const {return data_t;}
|
||||||
|
|
||||||
|
//! \~english Set timer tick function
|
||||||
|
//! \~russian Установить вызываемый метод
|
||||||
void setSlot(TimerEvent slot) {ret_func = slot;}
|
void setSlot(TimerEvent slot) {ret_func = slot;}
|
||||||
|
|
||||||
//! \brief Set timer tick function
|
//! \~english Set timer tick function
|
||||||
|
//! \~russian Установить вызываемый метод
|
||||||
void setSlot(std::function<void ()> slot) {ret_func = [slot](void *, int){slot();};}
|
void setSlot(std::function<void ()> slot) {ret_func = [slot](void *, int){slot();};}
|
||||||
|
|
||||||
//! \brief Set timer tick function
|
//! \~english Set timer tick function
|
||||||
|
//! \~russian Установить вызываемый метод
|
||||||
void setSlot(std::function<void (void *)> slot) {ret_func = [slot](void *d, int){slot(d);};}
|
void setSlot(std::function<void (void *)> slot) {ret_func = [slot](void *d, int){slot(d);};}
|
||||||
|
|
||||||
//! \brief Returns common data passed to tick functions
|
|
||||||
void * data() const {return data_t;}
|
|
||||||
|
|
||||||
void needLockRun(bool need) {lockRun = need;}
|
void needLockRun(bool need) {lockRun = need;}
|
||||||
EVENT_HANDLER0(void, lock) {mutex_.lock();}
|
EVENT_HANDLER0(void, lock) {mutex_.lock();}
|
||||||
EVENT_HANDLER0(void, unlock) {mutex_.unlock();}
|
EVENT_HANDLER0(void, unlock) {mutex_.unlock();}
|
||||||
|
|
||||||
//! \brief Returns if timer should exec \a maybeCallQueuedEvents() at every tick.
|
//! \~english Returns if timer should exec \a maybeCallQueuedEvents() at every tick. By default \b true
|
||||||
//! By default \b true
|
//! \~russian Возвращает должен ли таймер вызывать \a maybeCallQueuedEvents() каждый тик. По умолчанию \b true
|
||||||
bool isCallQueuedEvents() const {return callEvents;}
|
bool isCallQueuedEvents() const {return callEvents;}
|
||||||
|
|
||||||
//! \brief If set timer exec \a maybeCallQueuedEvents() at every tick.
|
//! \~english Set timer exec \a maybeCallQueuedEvents() at every tick
|
||||||
//! By default \b true
|
//! \~russian Установает должен ли таймер вызывать \a maybeCallQueuedEvents() каждый тик
|
||||||
void setCallQueuedEvents(bool yes) {callEvents = yes;}
|
void setCallQueuedEvents(bool yes) {callEvents = yes;}
|
||||||
|
|
||||||
//! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot.
|
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
||||||
|
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
|
||||||
void addDelimiter(int delim, TimerEvent slot = 0) {delims << Delimiter(slot, delim);}
|
void addDelimiter(int delim, TimerEvent slot = 0) {delims << Delimiter(slot, delim);}
|
||||||
|
|
||||||
//! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot.
|
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
||||||
|
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
|
||||||
void addDelimiter(int delim, std::function<void ()> slot) {delims << Delimiter([slot](void *, int){slot();}, delim);}
|
void addDelimiter(int delim, std::function<void ()> slot) {delims << Delimiter([slot](void *, int){slot();}, delim);}
|
||||||
|
|
||||||
//! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot.
|
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
||||||
|
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
|
||||||
void addDelimiter(int delim, std::function<void (void *)> slot) {delims << Delimiter([slot](void *d, int){slot(d);}, delim);}
|
void addDelimiter(int delim, std::function<void (void *)> slot) {delims << Delimiter([slot](void *d, int){slot(d);}, delim);}
|
||||||
|
|
||||||
//! \brief Remove all frequency delimiters \b delim.
|
//! \~english Remove all frequency delimiters "delim"
|
||||||
|
//! \~russian Удаляет все делители частоты "delim"
|
||||||
void removeDelimiter(int delim) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].delim == delim) {delims.remove(i); i--;}}
|
void removeDelimiter(int delim) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].delim == delim) {delims.remove(i); i--;}}
|
||||||
|
|
||||||
EVENT_HANDLER0(void, clearDelimiters) {delims.clear();}
|
EVENT_HANDLER0(void, clearDelimiters) {delims.clear();}
|
||||||
@@ -197,33 +220,58 @@ public:
|
|||||||
//! \handlers
|
//! \handlers
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
/** \fn bool start()
|
//! \fn void setInterval(double ms)
|
||||||
* \brief Start timer with \a interval() loop delay
|
//! \~english Set timer loop delay in milliseconds
|
||||||
* \details Start execution of timer functions with frequency = 1 / msecs Hz. */
|
//! \~russian Установить интервал таймера "ms" миллисекунд
|
||||||
|
|
||||||
/** \fn bool start(double msecs)
|
//! \fn bool start()
|
||||||
* \brief Start timer with \b msecs loop delay
|
//! \~english Start timer with \a interval() loop delay
|
||||||
* \details Start execution of timer functions with frequency = 1. / msecs Hz.
|
//! \~russian Запустить таймер с интервалом \a interval()
|
||||||
* Instead of \a start(int msecs) function this variant allow start timer
|
//! \~\details
|
||||||
* with frequencies more than 1 kHz */
|
//! \~english
|
||||||
|
//! Start execution of timer functions with frequency = 1 / msecs Hz
|
||||||
|
//! \~russian
|
||||||
|
//! Запускает таймер с частотой = 1 / msecs Гц
|
||||||
|
|
||||||
|
//! \fn bool start(double msecs)
|
||||||
|
//! \~english Start timer with "msecs" loop delay
|
||||||
|
//! \~russian Запустить таймер с интервалом "msecs"
|
||||||
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! Start execution of timer functions with frequency = 1. / msecs Hz.
|
||||||
|
//! Instead of \a start(int msecs) this function allow start timer
|
||||||
|
//! with frequencies more than 1 kHz
|
||||||
|
//! \~russian
|
||||||
|
//! Запускает таймер с частотой = 1 / msecs Гц. В отличии от
|
||||||
|
//! \a start(int msecs) этот метод позволяет запустить таймер с частотой
|
||||||
|
//! более 1 кГц
|
||||||
|
|
||||||
//! \fn bool restart()
|
//! \fn bool restart()
|
||||||
//! \brief Stop and start timer with \a interval() loop delay
|
//! \~english Stop and start timer with \a interval() loop delay
|
||||||
|
//! \~russian Остановить и запустить таймер с интервалом \a interval()
|
||||||
|
|
||||||
//! \fn bool stop(bool wait = true)
|
//! \fn bool stop(bool wait = true)
|
||||||
//! \brief Stop timer and wait for it finish if "wait"
|
//! \~english Stop timer and wait for it finish if "wait"
|
||||||
|
//! \~russian Остановить таймер и если "wait" то дождаться остановки
|
||||||
|
|
||||||
//! \fn void clearDelimiters()
|
//! \fn void clearDelimiters()
|
||||||
//! \brief Remove all frequency delimiters
|
//! \~english Remove all frequency delimiters
|
||||||
|
//! \~russian Удаляет все делители частоты
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
//! \events
|
//! \events
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
/** \fn void tickEvent(void * data, int delimiter)
|
//! \fn void tickEvent(void * data, int delimiter)
|
||||||
* \brief Raise on timer tick
|
//! \~english Raise on timer tick
|
||||||
* \details \b Data can be set with function \a setData(void * data) or from constructor.
|
//! \~russian Вызывается каждый тик таймера
|
||||||
* \b Delimiter is frequency delimiter, 1 for main loop. */
|
//! \~\details
|
||||||
|
//! \~english
|
||||||
|
//! "data" can be set with function \a setData() or from constructor.
|
||||||
|
//! "delimiter" is frequency delimiter, 1 for main loop.
|
||||||
|
//! \~russian
|
||||||
|
//! "data" устанавливается методом \a setData() или в конструкторе.
|
||||||
|
//! "delimiter" - делитель частоты, 1 для основного цикла
|
||||||
|
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
@@ -243,8 +291,7 @@ protected:
|
|||||||
static void tickImpS(PITimer * t) {t->tickImp();}
|
static void tickImpS(PITimer * t) {t->tickImp();}
|
||||||
void tickImp();
|
void tickImp();
|
||||||
|
|
||||||
//! Virtual timer execution function, similar to "slot" or event \a void timeout(void * data, int delimiter).
|
//! Timer execution function, similar to "slot" or event \a timeout(). By default does nothing
|
||||||
//! By default is empty.
|
|
||||||
virtual void tick(void * data_, int delimiter) {}
|
virtual void tick(void * data_, int delimiter) {}
|
||||||
|
|
||||||
void * data_t;
|
void * data_t;
|
||||||
|
|||||||
Reference in New Issue
Block a user