Well, a thread-safeness comes at cost .
ZeroMQ, since the very earliest version ( you refer to API ver. 2.1, while there are API versions past 4.2+ released and available in 2018/Q2+ ), was being built under a shared set of values a.k.a. a Zen-of-Zero, which strives to make things happen as-efficient-as-possible, in a resource-friendly manner and having acquired only a reasonable amount ( best none at all ) latency.
May see recent efforts to add thread-safety in ZeroMQ 4.2+ re-factoring
yet, this does not mean, this could be achieved cost-free, does it?
No one would be harmed, if using proper tools in a proper manner, would he?
Yet, no one may ignore a principal uncertainty of which ZeroMQ API version will appear in the domain of deployment, so relying on a feature available in newer API versions need not prove itself to be valid for each ( remote ) agents met during the life-span, so be cautious.
Anyway, the Akka
note warns, that as-is compatibility was frozen onto API v.2 level:
The currently used version of zeromq-scala-bindings
is only compatible with zeromq 2; zeromq 3 is not supported.
So, how ?
If indeed in a need to mix several different event-loops ( as indicated above ), I would opt for delegating the task to a set of independently operating ( be it colocated or distributed ) Context()
-instances, rather than trying to share any Socket()
-AccessPoint-level instances or trying to use a "pinned"-promise, just-mediated by an external ( concurrently co-existent ) non-ZeroMQ event-loop framework.
Clean "share-nothing" ZeroMQ designs are way safer and way faster, than trying an art of juggling more and more design-artifacts ( and if your domain requires QA-procedures, the more if design validation and verification proofs are to get delivered before an acceptance may even get scheduled -- try to just imagine the costs of testing, QA / verification proofs for a wild mix of toys just wished to have a deterministic, non-blocking, error-free and robust/resilient field operations )
Beware :
ZeroMQ Socket()
-instance is not a tcp-socket-as-you-know-it. Best read about the main conceptual differences in ZeroMQ hierarchy in less than a five seconds or other posts and discussions here.
Context()
-instances have their own I/O-thread-pools under their own domain-of-control, also having a "DMA"-alike mapper between a respective Context
's Socket()
-instance permitted affinity to the respective Context
's (groups of) I/O-thread(s), so a global view on "pinning" may not affect the intended resource-mapping preferences.
Last, but not least - Akka-port specific configurations ,
that do not match the ZeroMQ native API defaults :
#####################################
# Akka ZeroMQ Reference Config File #
#####################################
# This is the reference config file that contains all the default settings.
# Make your edits/overrides in your application.conf.
akka {
zeromq {
# The default timeout for a poll on the actual zeromq socket.
poll-timeout = 100ms
# Timeout for creating a new socket
new-socket-timeout = 5s
socket-dispatcher {
# A zeromq socket needs to be pinned to the thread that created it.
# Changing this value results in weird errors and race conditions within
# zeromq
executor = thread-pool-executor
type = "PinnedDispatcher"
thread-pool-executor.allow-core-timeout = off
}
}
}