Is there a built-in concurrency control in boost::interprocess::message_queue? - boost

In a multiple producer-single consumer setting, is there a built-in concurrency control mechanism among the producer processes that are calling send() on the message_queue?
What happens if there are multiple instances of the consumer processes all calling receive() on the message_queue?

To the question whether message_queue is thread-safe, the answer is yes.
message_queue is implemented in terms of shared_memory_object using some control structures (ipcdetail::mq_hdr_t) which include synchronization primitives (like interprocess_mutex).
These are used to prevent unguarded concurrent access.

Related

Actors: Thread based vs Event driven

Reading about actor based programming, I came across thread based actors and event driven actors.
What's the difference between two? And when to use which?
The Actor Model itself is a concurrency specification. From the Actor Model perspective, there is no concept of "events", "threads" or a "processes", only Actors and messages.
This is actually one of the benefits of the Actor model in that it takes a different approach to concurrency that provides greater isolation. Any shared information must be exchanged via messages and the processing of a particular message is atomic, so no special concurrency synchronization techniques are required during execution of an Actor's message handler.
By contrast, threads run in a shared memory space, which requires careful coordination of memory updates (via mutexes and locks) or simulated exchange of information (via queues... with locks or mutexes). Processes implement a concurrency model that is more similar to Actors in that they provide more isolation, but do not have native support for message exchange so the information exchange must often be constructed and managed within the process via pipes or sockets and corresponding protocols and resource management; Actors provide this message exchange functionality "out of the box" as it were.
Practically speaking, most Operating Systems provide the "process" and "thread" concurrency implementations instead of Actors, so the Actor framework you utilize will need to map your Actors onto the operating system's underlying concurrency model. Some do this by implementing each Actor as a separate thread, some by implementing Actors as separate processes, some by using one or more threads and iterating through the set of Actors to pass messages. Even event-driven implementations such as Beam (the Erlang VM) will need to perform this mapping if they wish to utilize multiple processor contexts and there is an Operating System between the VM and the hardware.
When you write your Actors, you are writing to that concurrency abstraction and should not be concerned with any concurrency model remapping handled by your Actor Framework: that is the purpose and the purview of the framework.
Unfortunately, since the OS manages the system resources, and the OS's concurrency model (along with your language) is usually built around a thread and/or process model, you will need to consider the effect of the mapping when working with system resources. For example, if your Actor is written in C and will be making a blocking read() syscall on a file or socket, an event driven model will cause all Actors to halt, whereas a thread- or process-based Actor model should allow the other Actors to continue processing while the other Actor is blocked on the read() call. I this same scenario but using CPython (for example), both an event-driven and a threaded Actor model would still block all other Actors due to the CPython GIL, but a process-based Python Actor model would still be able to allow concurrent Actor execution. Many Actor Frameworks will provide additional functionality to help maintain the Actor model abstractions when using system resources, so you will need to check the details of your Framework when writing Actors that interact with OS-managed resources (especially in a blocking manner).
Some Actor Frameworks are capable of changing the implementation mode based on startup configuration parameters (e.g. running as event-driven, threaded, or process-based depending on a start parameter). This can be very useful; for example, simple testing using a cooperative, single-threaded implementation allows repeatable and understandable test results while the production application still runs with full concurrency and no modifications.
In general, when writing Actors you should try to use Actor-based concurrency practices and migrate any external interfaces that might be affected by the underlying implementation to the edge of your design where they can be easily redesigned if needed.

boost asio concurrent async_read and async_write

Looking at the documentation it looks like the TCP socket object is not thread-safe. So I cannot issue async_read from one thread and async_write concurrently from another thread? Also I would guess it applies to boost::asio::write() as well?
Can I issue write() - synchronous, while I do async_read from another thread?
If that is not safe, then only way is probably to get the socket native handle
and use synchronous linux mechanisms to achieve concurrent read and writes. I have an application where the reads and writes are actually independent.
It is thread-safe for the use-cases you listed. You can read in one thread, and write in another. And you can use the synchronous as well as asynchronous operations for that.
You will however run into problems, if you try to do one dedicated operation type (e.g. reads) from more than one thread. Especially if you are using the freestanding/composed operations (boost::asio::read(socket) instead of socket.read_some(). The reason for this is one the primitive operations are atomic / threadsafe. And the composed operations are working by calling multiple times into the primitives.

What does JMS Session single-threadedness mean?

What is the exact nature of the thread-unsafety of a JMS Session and its associated constructs (Message, Consumer, Producer, etc)? Is it just that access to them must be serialized, or is it that access is restricted to the creating thread only?
Or is it a hybrid case where creation can be distinguished from use, i.e. one thread can create them only and then another thread can be the only one to use them? This last possibility would seem to contradict the statement in this answer which says "In fact you must not use it from two different threads at different times either!"
But consider the "Server Side" example code from the ActiveMQ documentation.
The Server class has data members named session (of type Session) and replyProducer (of type MessageProducer) which are
created in one thread: whichever one invokes the Server() constructor and thereby invokes the setupMessageQueueConsumer() method with the actual creation calls; and
used in another thread: whichever one invokes the onMessage() asynchronous callback.
(In fact, the session member is used in both threads too: in one to create the replyProducer member, and in the other to create a message.)
Is this official example code working by accident or by design? Is it really possible to create such objects in one thread and then arrange for another thread to use them?
(Note: in other messaging infrastructures, such as Solace, it's possible to specify the thread on which callbacks occur, which could be exploited to get around this "thread affinity of objects" restriction, but no such API call is defined in JMS, as far as I know.)
JMS specification says a session object should not be used across threads except when calling Session.Close() method. Technically speaking if access to Session object or it's children (producer, consumer etc) is serialized then Session or it's child objects can be accessed across threads. Having said that, since JMS is an API specification, it's implementation differs from vendor to vendor. Some vendors might strictly enforce the thread affinity while some may not. So it's always better to stick to JMS specification and write code accordingly.
The official answer appears to be a footnote to section 4.4. "Session" on p.60 in the JMS 1.1 specification.
There are no restrictions on the number of threads that can use a Session object or those it creates. The restriction is that the resources of a Session should not be used concurrently by multiple threads. It is up to the user to insure that this concurrency restriction is met. The simplest way to do this is to use one thread. In the case of asynchronous delivery, use one thread for setup in stopped mode and then start asynchronous delivery. In more complex cases the user must provide explicit synchronization.
Whether a particular implementation abides by this is another matter, of course. In the case of the ActiveMQ example, the code is conforming because all inbound message handling is through a single asynchronous callback.

boost.asio - do i need to use locks if sharing database type object between different async handlers?

I'm making a little server for a project, I have a log handler class which contains a log implemented as a map and some methods to act on it (add entry, flush to disk, commit etc..)
This object is instantiated in the server Class, and I'm passing the address to the session so each session can add entries to it.
The sessions are async, the log writes will happen in the async_read callback. I'm wondering if this will be an issue and if i need to use locks?
The map format is map<transactionId map<sequenceNum, pair<head, body>>, each session will access a different transactionId, so there should be no clashes as far as i can figure. Also hypothetically, if they were all writing to the same place in memory -- something large enough that the operation would not be atomic; would i need locks? As far as I understand each async method dispatches a thread to handle the operation, which would make me assume yes. At the same time I read that one of the great uses of async functions is the fact that synchronization primitives are not needed. So I'm a bit confused.
First time using ASIO or any type of asynchronous functions altogether, and i'm not a very experienced coder. I hope the question makes sense! The code seems to run fine so far, but i'm curios if it's correct.
Thank you!
Asynchronous handlers will only be invoked in application threads processing the io_service event loop via run(), run_one(), poll(), or poll_one(). The documentation states:
Asynchronous completion handlers will only be called from threads that are currently calling io_service::run().
Hence, for a non-thread safe shared resource:
If the application code only has one thread, then there is neither concurrency nor race conditions. Thus, no additional form of synchronization is required. Boost.Asio refers to this as an implicit strand.
If the application code has multiple threads processing the event-loop and the shared resource is only accessed within handlers, then synchronization needs to occur, as multiple threads may attempt to concurrently access the shared resource. To resolve this, one can either:
Protect the calls to the shared resource via a synchronization primitive, such as a mutex. This question covers using mutexes within handlers.
Use the same strand to wrap() the ReadHandlers. A strand will prevent concurrent invocation of handlers dispatched through it. For more details on the usage of strands, particularly for composed operations, such as async_read(), consider reading this answer.
Rather than posting the entire ReadHandler into the strand, one could limit interacting with the shared resource to a specific set of functions, and these functions are posted as CompletionHandlers to the same strand. This subtle difference between this and the previous solution is the granularity of synchronization.
If the application code has multiple threads and the shared resource is accessed from threads processing the event loop and from threads not processing the event loop, then synchronization primitives, such as a mutex, needs to be used.
Also, even if a shared resource is small enough that writes and reads are always atomic, one should prefer using explicit and proper synchronization. For example, although the write and read may be atomic, without proper memory fencing to guarantee memory visibility, a thread may not observe a chance in memory even though the actual memory has chanced. Boost.Asio's will perform the proper memory barriers to guarantee visibility. For more details, on Boost.Asio and memory barriers, consider reading this answer.

What is the difference between event driven model and reactor pattern? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 4 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
From the wikipedia Reactor Pattern article:
The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs.
It named a few examples, e.g. nodejs, twisted, eventmachine
But what I understand that above is popular event driven framework, so make them also a reactor pattern framework?
How to differentiate between these two? Or they are the same?
The reactor pattern is more specific than "event driven programming". It is a specific implementation technique used when doing event driven programming. However, the term is not used with much accuracy in typical conversation, so you should be careful about using it and expecting your audience to understand you, and you should be careful in how you interpret the term when you encounter its use.
One way to look at the reactor pattern is to consider it closely related to the idea of "non-blocking" operations. The reactor sends out notifications when certain operations can be completed without blocking. For example, select(2) can be used to implement the reactor pattern for reading from and writing to sockets using the standard BSD socket APIs (recv(2), send(2), etc). select will tell you when you can receive bytes from a socket instantly - because the bytes are present in the kernel receiver buffer for that socket, for example.
Another pattern you might want to consider while thinking about these ideas is the proactor pattern. In contrast to the reactor pattern, the proactor pattern has operations start regardless of whether they can finish immediately or not, has them performed asynchronously, and then arranges to deliver notification about their completion.
The Windows I/O Completion Ports (IOCP) API is one example where the proactor pattern can be seen. When performing a send on a socket with IOCP, the send operation is started regardless of whether there is any room in the kernel send buffer for that socket. The send operation continues (in another thread, perhaps a thread in the kernel) while the WSASend call completes immediately. When the send actually completes (meaning only that the bytes being sent have been copied into the kernel send buffer for that socket), a callback function supplied to the WSASend call is invoked (in a new thread in the application).
This approach of starting operations and then being notified when they are complete is central to the idea of asynchronous operations. Compare it to non-blocking operations where you wait until an operation can complete immediately before attempting to perform it.
Either approach can be used for event driven programming. Using the reactor pattern, a program waits for the event of (for example) a socket being readable and then reads from it. Using the proactor pattern, the program instead waits for the event of a socket read completing.
Strictly speaking, Twisted misuses the term reactor. The Twisted reactor which is based on select(2) (twisted.internet.selectreactor) is implemented using non-blocking I/O, which is very reactor-like. However, the interface it exposes to application code is asynchronous, making it more proactor-like. Twisted also has a reactor based on IOCP. This reactor exposes the same asynchronous application-facing API and uses the proactor-like IOCP APIs. This hybrid approach, varying from platform to platform in its details, makes neither the term "reactor" nor "proactor" particularly accurate, but since the API exposed by twisted.internet.reactor is basically entirely asynchronous instead of non-blocking, proactor would probably have been a better choice of name.
I think that this separation "non-blocking" and "asynchronous" is wrong, as the main implication of "asynchronous" is "non-blocking". Reactor pattern is about asynchronous (so non-blocking) calls, but synchronous (blocking) processing of those calls. Proactor is about asynchronous (non-blocking) calls and asynchronous (non-blocking) processing of those calls.
To handle TCP connections, there are two competing web architectures, namely thread-based architecture and event-driven architecture.
Thread-Based Architecture
The oldest way of implementing a multi-threaded server is following the “thread per connection” approach. In order to control and limit the number of running threads, a single dispatcher thread can be used along with a bounded blocking queue and a thread pool.
The dispatcher blocks on a TCP socket for new connections and offers them to the bounded blocking queue. TCP connections exceeding the bound of the queue will be dropped allowing the accepted connections to operate with a desirable and predictable latency.
Event-Driven Architecture
Separating threads from connections, event-driven architecture only allows threads to be used for events on specific handlers.
This creative concept allows Reactor Pattern to come out of the shelf and show off. A system built on this architecture consists of event creators and event consumers.
The Reactor Pattern
The reactor pattern is the most popular implementation technique of event-driven architecture for TCP connection handling. In simple terms, it uses a single-threaded event loop, blocking on events and dispatches those events to corresponding handlers.
There is no need for other threads to block on I/O, as long as handlers for events are registered to take care of them. Considering a TCP connection, we can easily refer events to these instances: connected, input-ready, output-ready, timeout, and disconnected.
Reactor pattern decouples the modular application-level code from reusable reactor implementation. To achieve that, the architecture of the reactor pattern consists of two important participants — Reactor and Handlers.
Reactor
A Reactor runs in a separate thread, and it is reacting to the I/O events such as connected, input-ready, output-ready, timeout and disconnected, by dispatching the work to the appropriate registered handler.
Handlers
A Handler performs the actual work or the response that needs to be done with an I/O event. A Reactor responds to I/O events by dispatching the appropriate handler.
“Pattern Languages of Program Design” by Jim Coplien and Douglas C. Schmidt which was published way back in 1995, is one of the books that has explained the Reactor Pattern in detail.

Resources