diff --git a/.gitignore b/.gitignore
index a8ac5df5..d1047098 100644
--- a/.gitignore
+++ b/.gitignore
@@ -117,6 +117,7 @@ test_getsockopt_memset
test_setsockopt
test_stream_exceeds_buffer
test_poller
+test_timers
tests/test*.log
tests/test*.trs
src/platform.hpp*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a2d03fb0..ee72c7af 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -449,6 +449,7 @@ set(cxx-sources
zmq_utils.cpp
decoder_allocators.cpp
socket_poller.cpp
+ timers.cpp
config.hpp)
set(rc-sources version.rc)
diff --git a/Makefile.am b/Makefile.am
index 209af418..ca152a38 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -179,6 +179,8 @@ src_libzmq_la_SOURCES = \
src/tcp_listener.hpp \
src/thread.cpp \
src/thread.hpp \
+ src/timers.cpp \
+ src/timers.hpp \
src/tipc_address.cpp \
src/tipc_address.hpp \
src/tipc_connecter.cpp \
@@ -376,7 +378,8 @@ test_apps = \
tests/test_socketopt_hwm \
tests/test_heartbeats \
tests/test_stream_exceeds_buffer \
- tests/test_poller
+ tests/test_poller \
+ tests/test_timers
tests_test_system_SOURCES = tests/test_system.cpp
tests_test_system_LDADD = src/libzmq.la
@@ -587,6 +590,9 @@ tests_test_stream_exceeds_buffer_LDADD = src/libzmq.la
tests_test_poller_SOURCES = tests/test_poller.cpp
tests_test_poller_LDADD = src/libzmq.la
+tests_test_timers_SOURCES = tests/test_timers.cpp
+tests_test_timers_LDADD = src/libzmq.la
+
if !ON_MINGW
if !ON_CYGWIN
@@ -729,4 +735,3 @@ dist-hook:
maintainer-clean-local:
-rm -rf $(top_srcdir)/config
-
diff --git a/include/zmq.h b/include/zmq.h
index f53283f8..88525bd8 100644
--- a/include/zmq.h
+++ b/include/zmq.h
@@ -451,6 +451,21 @@ ZMQ_EXPORT int zmq_poller_modify_fd (void *poller, int fd, short events);
ZMQ_EXPORT int zmq_poller_remove_fd (void *poller, int fd);
#endif
+/******************************************************************************/
+/* Scheduling timers */
+/******************************************************************************/
+
+typedef void (zmq_timer_fn)(int timer_id, void *arg);
+
+ZMQ_EXPORT void *zmq_timers_new ();
+ZMQ_EXPORT int zmq_timers_close (void *timers);
+ZMQ_EXPORT int zmq_timers_add (void *timers, size_t interval, zmq_timer_fn handler, void *arg);
+ZMQ_EXPORT int zmq_timers_cancel (void *timers, int timer_id);
+ZMQ_EXPORT int zmq_timers_set_interval (void *timers, int timer_id, size_t interval);
+ZMQ_EXPORT int zmq_timers_reset (void *timers, int timer_id);
+ZMQ_EXPORT long zmq_timers_timeout (void *timers);
+ZMQ_EXPORT int zmq_timers_execute (void *timers);
+
/******************************************************************************/
/* Message proxying */
/******************************************************************************/
@@ -542,4 +557,3 @@ ZMQ_EXPORT void zmq_threadclose (void* thread);
#endif
#endif
-
diff --git a/src/timers.cpp b/src/timers.cpp
new file mode 100644
index 00000000..f2f3ee99
--- /dev/null
+++ b/src/timers.cpp
@@ -0,0 +1,169 @@
+/*
+Copyright (c) 2007-2015 Contributors as noted in the AUTHORS file
+
+This file is part of libzmq, the ZeroMQ core engine in C++.
+
+libzmq is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License (LGPL) as published
+by the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+As a special exception, the Contributors give you permission to link
+this library with independent modules to produce an executable,
+regardless of the license terms of these independent modules, and to
+copy and distribute the resulting executable under terms of your choice,
+provided that you also meet, for each linked independent module, the
+terms and conditions of the license of that module. An independent
+module is a module which is not derived from or based on this library.
+If you modify this library, you must extend this exception to your
+version of the library.
+
+libzmq is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
+*/
+
+#include "timers.hpp"
+#include "err.hpp"
+
+zmq::timers_t::timers_t () :
+tag (0xCAFEDADA),
+next_timer_id (0)
+{
+
+}
+
+zmq::timers_t::~timers_t ()
+{
+ // Mark the timers as dead
+ tag = 0xdeadbeef;
+}
+
+bool zmq::timers_t::check_tag ()
+{
+ return tag == 0xCAFEDADA;
+}
+
+int zmq::timers_t::add (size_t interval_, timers_timer_fn handler_, void* arg_)
+{
+ uint64_t when = clock.now_ms() + interval_;
+ timer_t timer = {++next_timer_id, interval_, handler_, arg_};
+ timers.insert (timersmap_t::value_type (when, timer));
+
+ return timer.timer_id;
+}
+
+int zmq::timers_t::cancel (int timer_id_)
+{
+ cancelled_timers_t::iterator it = cancelled_timers.find (timer_id_);
+
+ if (it != cancelled_timers.end ()) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ cancelled_timers.insert (timer_id_);
+
+ return 0;
+}
+
+int zmq::timers_t::set_interval (int timer_id_, size_t interval_)
+{
+ for (timersmap_t::iterator it = timers.begin (); it != timers.end (); ++it) {
+ if (it->second.timer_id == timer_id_) {
+ timer_t timer = it->second;
+ timer.interval = interval_;
+ uint64_t when = clock.now_ms() + interval_;
+ timers.erase (it);
+ timers.insert (timersmap_t::value_type (when, timer));
+
+ return 0;
+ }
+ }
+
+ errno = EINVAL;
+ return -1;
+}
+
+int zmq::timers_t::reset (int timer_id_) {
+ for (timersmap_t::iterator it = timers.begin (); it != timers.end (); ++it) {
+ if (it->second.timer_id == timer_id_) {
+ timer_t timer = it->second;
+ uint64_t when = clock.now_ms() + timer.interval;
+ timers.erase (it);
+ timers.insert (timersmap_t::value_type (when, timer));
+
+ return 0;
+ }
+ }
+
+ errno = EINVAL;
+ return -1;
+}
+
+long zmq::timers_t::timeout ()
+{
+ timersmap_t::iterator it = timers.begin ();
+
+ uint64_t now = clock.now_ms();
+
+ while (it != timers.end ()) {
+ cancelled_timers_t::iterator cancelled_it = cancelled_timers.find (it->second.timer_id);
+
+ // Live timer, lets return the timeout
+ if (cancelled_it == cancelled_timers.end ()) {
+ if (it->first > now)
+ return it->first - now;
+ else
+ return 0;
+ }
+
+ // Let's remove it from the begining of the list
+ timersmap_t::iterator old = it;
+ ++it;
+ timers.erase (old);
+ cancelled_timers.erase (cancelled_it);
+ }
+
+ // Wait forever as no timers are alive
+ return -1;
+}
+
+int zmq::timers_t::execute ()
+{
+ timersmap_t::iterator it = timers.begin ();
+
+ uint64_t now = clock.now_ms();
+
+ while (it != timers.end ()) {
+ cancelled_timers_t::iterator cancelled_it = cancelled_timers.find (it->second.timer_id);
+
+ // Dead timer, lets remove it and continue
+ if (cancelled_it != cancelled_timers.end ()) {
+ timersmap_t::iterator old = it;
+ ++it;
+ timers.erase (old);
+ cancelled_timers.erase (cancelled_it);
+ continue;
+ }
+
+ // Map is ordered, if we have to wait for current timer we can stop.
+ if (it->first > now)
+ break;
+
+ timer_t timer = it->second;
+
+ timer.handler (timer.timer_id, timer.arg);
+
+ timersmap_t::iterator old = it;
+ ++it;
+ timers.erase (old);
+ timers.insert (timersmap_t::value_type (now + timer.interval, timer));
+ }
+
+ return 0;
+}
diff --git a/src/timers.hpp b/src/timers.hpp
new file mode 100644
index 00000000..86cab51b
--- /dev/null
+++ b/src/timers.hpp
@@ -0,0 +1,108 @@
+/*
+Copyright (c) 2007-2015 Contributors as noted in the AUTHORS file
+
+This file is part of libzmq, the ZeroMQ core engine in C++.
+
+libzmq is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License (LGPL) as published
+by the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+As a special exception, the Contributors give you permission to link
+this library with independent modules to produce an executable,
+regardless of the license terms of these independent modules, and to
+copy and distribute the resulting executable under terms of your choice,
+provided that you also meet, for each linked independent module, the
+terms and conditions of the license of that module. An independent
+module is a module which is not derived from or based on this library.
+If you modify this library, you must extend this exception to your
+version of the library.
+
+libzmq is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
+*/
+
+#ifndef __ZMQ_TIMERS_HPP_INCLUDED__
+#define __ZMQ_TIMERS_HPP_INCLUDED__
+
+#include
+#include