For some reason that I didn't get to the root cause, gcc 4.8.1 (that I'm
stuck with) does not like the initializer for `unique_ptr` implemented
as a lambda:
```
third_party/zmqcpp/repo/zmq.hpp: In constructor 'zmq::poller_t<T>::poller_t() [with T = std::function<void(zmq::event_flags)>]':
third_party/zmqcpp/repo/zmq.hpp:1871:5: error: converting to 'std::unique_ptr<void, zmq::poller_t<std::function<void(zmq::event_flags)> >::destroy_poller_t>' from initializer list would use explicit constructor 'std::unique_ptr<_Ty, _Dx>::unique_ptr(std::unique_ptr<_Ty, _Dx>::pointer) [with _Ty = void; _Dx = zmq::poller_t<std::function<void(zmq::event_flags)> >::destroy_poller_t; std::unique_ptr<_Ty, _Dx>::pointer = void*]'
poller_t() = default;
^
In file included from networking/ipc/ipc.cc:6:0:
third_party/zmqcpp/repo/zmq_addon.hpp: At global scope:
third_party/zmqcpp/repo/zmq_addon.hpp:447:40: note: synthesized method 'zmq::poller_t<T>::poller_t() [with T = std::function<void(zmq::event_flags)>]' first required here
poller_t<handler_type> base_poller{};
^
In file included from ./networking/ipc/ipc.h:13:0,
from networking/ipc/ipc.cc:1:
third_party/zmqcpp/repo/zmq.hpp: In constructor 'zmq::poller_t<T>::poller_t() [with T = zmq::socket_t]':
third_party/zmqcpp/repo/zmq.hpp:1871:5: error: converting to 'std::unique_ptr<void, zmq::poller_t<zmq::socket_t>::destroy_poller_t>' from initializer list would use explicit constructor 'std::unique_ptr<_Ty, _Dx>::unique_ptr(std::unique_ptr<_Ty, _Dx>::pointer) [with _Ty = void; _Dx = zmq::poller_t<zmq::socket_t>::destroy_poller_t; std::unique_ptr<_Ty, _Dx>::pointer = void*]'
poller_t() = default;
^
networking/ipc/ipc.cc: In member function 'void networking::ipc::Ipc::ThreadMain()':
networking/ipc/ipc.cc:313:36: note: synthesized method 'zmq::poller_t<T>::poller_t() [with T = zmq::socket_t]' first required here
::zmq::poller_t<::zmq::socket_t> poller;
^
```
This moves the initialization to constructor, and makes gcc happy.
This to avoid the following warning with the '-Wold-style-cast' flag enabled :
./zmq.hpp:763:29: warning: use of old-style cast [-Wold-style-cast]
return (size_t) nbytes;
^
./zmq.hpp: In member function ‘size_t zmq::socket_t::recv(void*, size_t, int)’:
./zmq.hpp:793:29: warning: use of old-style cast [-Wold-style-cast]
return (size_t) nbytes;
Solution: Implement for socket_t, context_t, message_t and poller_t
Additionally remove dependency on <functional> by refactoring poller_t
and remove unused <unordered_map> include.
Currently cppzmq as relatively simple and header only library depends on rather
complex unit test framework googletest.
Current issues:
- Googletest requires downloading and building it every time on travis
as cache support is limited there
- Googletest build is signifficant with comparison to cppzmq unittests
total runtime
Solution: Port existing tests to Catch - header only C++ framework and
gain ~20% build speed up on travis.
Why Catch?
It is well know C++ header only testing framework. It works well, it is
being kept up to date and maintainers seem to pay attention to
community's comments and issues.
We can not use Catch2 currently as we still support pre-C++11 compilers.
This commit introduces new socket_type enumeration values as well
as the following supporting functions:
socket_t::join()
socket_t::leave()
message_t::group()
message_t::set_group()
For header only library like cppzmq, whitespace style inherited from
libzmq is too restrictive.
Solution: relaxing whitespace before parens from always to in control
statements only, increased max column width from 80 to 85 and removing
requirement of whitespace after template keyword.
Solution: Constructor logic moved to the same place where cleanup is and
marking constructor `default`. Init/cleanup code is in one pleace making
it easier to read/maintain.
Latest modification to the poller made move constructor and move
assigment operator not complete. In order to prevent that in the future
poller should be default movable. Unique pointer has been used to
manager zmq_poller. That makes code simpler and safer now.
* Problem: poller can segfault when modified from registred handler.
It is possible that a user would like to add/remove sockets from
handlers. As handlers and poll items might be removed while not
being processed yet - we have a segfault situation.
Provided unit test `remove_from_handler` demonstrates the problem.
Solution: Modify internal poll item data structure only after processing
of events is finished.
Please not that events processing path performance remains the same when there are
no modification (add/remove) to the poller (no rebuild) - main real use case.
As an effect of changes `size()` method has been removed as it does not
represent any meaningful information anymore. There are active and pending
(waiting for rebuild) poll items so two different sizes. User can
easily track on their side number of registered sockets if original size
information is needed.
`wait` method returns number of processed sockets now. It might be
useful information to a user for no extra cost.
We have a deprecated method `add` in poller that contradicts purpose of a draft
API where it can change without deprecation period.
Solution: remove the method so we do not to maintain it anymore.
Solution: Added `modify` method based on `zmq_poller_modify` and test cases
covering it.
Reduced code duplication in existing test cases by introducing
`client_server_setup` helper struct.
Issue is reproducible in deprecated add method with empty handler
followed by wait that kicks in (covered by provided unit test).
I would prefer we remove this method completely as maintaining something
that we consider `deprecated` is unnecessary in `draft` API.
On adding invalid socket (e.g. after move) there was exception thrown
but leaving modified and unconsistent internal state.
Besides that there was no possibility to remove a socket that was moved
into.
Solutions: check for socket validity (added operator bool) and changed
internal unordered_map "handlers" to operator on zmq internal pointers.
Added two test cases covering the issues.
* Problem: Windows build broken because of multiple issues
Windows issues:
* missing includes files
Solution: added missing <memory> and <unordered_map>
Here <map> was replaced with <unordered_map> as there is no need for
sorted map.
* googletest fails because deprecation warning causing errors.
Solution: D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING option added.
* googletest fails because by default, new Visual Studio projects
link the C runtimes dynamically but Google Test links them statically.
Solution: gtest_force_shared_crt=ON option added.
Besides that adding appveyor.yml configuration to add Windows build to
CI in order to prevent accidental Windows build breakage.
For now only Debug configuration as Release requires more time to figure
out.
* Problem: Windows build takes too long
Solution: disabling tests and perf tools
* Problem: Windows unit_tests executable not finding lizmq dll.
Solution: copy libzmq dll to build bin directory.
* Problem: Windows build fails because wrong test path provided
* Added overload constructor (c++11 only) taking iteratable object.
It would be easier to use std::string, std::array etc to construct
a message now. Making it a draft for now in case it is too greedy
and needs to be more specialize.
* Added equal and not euqal operator to message_t as a recommended
and expected way of comparing objects in C++.
* deprecated C style equal method as operator== should be used instead
(point above).
* Added message_t test covering all available message_t's constructors
* Problem: Poller's handler not aware of event type.
It was possible to register a handler for more than one event types but
impossible to distinguish which event is being handled.
Now events are passed to a handler.
Besides that some other changes:
* new test covering changes in the poller
* modified existing tests to cover changes in the poller
* defined handler_t in poller_t scope for more convinient use
and simpler code
* helper loopback binder to be re-used in tests
* Problem: CMake build fails on Windows
Issue #199
It seems that with GCC on Linux <array> is implicitly included
by one of stl includes already in zmq.hpp but it breaks on Windows
with Visual Studio.
Adding explicit include for array.
Can not verify right now but this change is a good practice
so creating a pull request.
* Poller: array include not between C++11 guards
@sigiesec's recent commits with gtests and basics tests for zmq
types (thanks for that!) makes it too convinient to not add some more tests.
* Adding some simple tests for poller_t
* Stripped whitespaces from poller implementation.
Added a str() method and companion operator<<(std::ostream) similar to multipart_t.
Added some comments to mark the end of preprocessor instructions / class def / namespace def.
* Fix compile error for libzmq 4.2.1 and 4.2.2
When defined ZMQ_BUILD_DRAFT_API=1, you receive an error "'on_event_handshake_succeeded' was not declared in this scope"... which is correct for versions 4.2.1 and 4.2.2.
Function was renamed from 'on_event_handshake_succeed', fixed this by updating the function name.
There are two overloads of `poll` - one that has `-1` as the default value for the timeout, and one that does not have the timeout argument (which calls the previous one with -1 for the timeout). This makes it ambiguous for the compiler when `poll` is called without the timeout.
This patch removes the second overload as it is not needed since the first one already covers the same case.
Line 706 constructor was:
monitor_t() : socketPtr(NULL), monitor_socket{NULL} {}
but should be:
monitor_t() : socketPtr(NULL), monitor_socket(NULL) {}
Note change of bracket types for monitor_socket parameter.
This does not allaw to use monitor_t without a thread.
What is often OK but sometimes not.
Solution:
keep existing interface but add a non blocking alternative.
This can cause monitor_t to crash if used with a socket that was
constructed via the move constructor.
Solution: initialise the context pointer variable ctxptr in the move
constructor.
During introduction of EHOSTUNREACH, missing mapping between
EHOSTUNREACH errno and false/0 return code for socket's send()
calls was missing, throwing an exception.
To be consistent with the rest of wrappers (e.g. DONTWAIT), fix it
by handling this errno as a regular EAGAIN, and let the caller use
errno/zmq_errno() to branch on their code.