Why do we need to declare a constant as Shared Constant? - multithreading

In ESQL we have SHARED CONSTANTS, Why do we need them when they are constant and they don't change even if multiple threads access the same value.
DECLARE MYCONST SHARED CONSTANT CHAR 'My Constant';
OR in general I would like to know why do we need shared constants??

Using my immagination, you can declare a constant shared to not duplicate a BIG variable among Flows.
For Example, it could be useful in a multiple instances flow if you want to send a every-time-the-same message and you want to save time.
It could be already in memory with:
DECLARE MYVAR SHARED CONSTANT BLOB X'0000' ;
I think that this need is very much infrequent.
And even more infrequent to take advantage from this: if the blob is too big simply is counterproductive to put in a global variable.

According to this post, it takes more time to read a SHARED CONSTANT than a normal CONSTANT. There seems to be a locking mechanism for all shared variables, including constants.
But probably all non shared CONSTANTs are copied to the memory at the start of each flow instance. I would say, if you have a lot of constants and each flow only accesses a few of them, SHARED CONSTANTS are more performant.
If performance is an issue, I would test which option processes the data in less time. But there is no solution that is best for every single messageflow.

Related

How can tokio tasks access shared data in Rust?

I am creating a webserver using tokio. Whenever a client connection comes in, a green thread is created via tokio::spawn.
The main function of my web server is proxy. Target server information for proxy is stored as a global variable, and for proxy, all tasks must access the data. Since there are multiple target servers, they must be selected by round robin. So the global variable (struct) must have information of the recently selected server(by index).
Concurrency problems occur because shared information can be read/written by multiple tasks at the same time.
According to the docs, there seems to be a way to use Mutex and Arc or a way to use channel to solve this.
I'm curious which one you usually prefer, or if there is another way to solve the problem.
If it's shared data, you generally do want Arc, or you can leak a box to get a 'static reference (assuming that the data is going to exist until the program exits), or you can use a global variable (though global variables tends to impede testability and should generally be considered an anti-pattern).
As far as what goes in the Arc/Box/global, that depends on what your data's access pattern will be. If you will often read but rarely write, then Tokio's RwLock is probably what you want; if you're going to be updating the data every time you read it, then use Tokio's Mutex instead.
Channels make the most sense when you have separate parts of the program with separate responsibilities. It doesn't work as well to update multiple workers with the same changes to data, because then you get into message ordering problems that can result in each worker's state disagreeing about something. (You get many of the problems of a distributed system without any of the benefits.)
Channels can work if there is a single entity responsible for maintaining the data, but at that point there isn't much benefit over using some kind of mutual exclusion mechanism; it winds up being the same thing with extra steps.

What is thread local storage? Why we need it?

I am reading the Threads in OS concepts and i come across "thread local storage (TLS)". What I understood is that the TLS is similar to static or global data, but it is more unique to individual thread. Its bit confusing on what is unique here?
Why can't we pass the data through runner (i.e., thread's actual codes) functions as params to this function?
Static and global data are shared across all the threads. If you modified a global/static variable it is visible to all the threads. Unlike global/shared variable if you create a variable in TLS, every thread has its own copy of the variable, i.e. changes to the variable is local to the thread. Unlike global variable where an access is made through ds segment, the TLS variable are accessed using (gs/fs) segment. A good way to learn about it is to look at the disassembly generated by the compiler.
Let's supposed you are working in Ada. In your Ada program you define a task (thread) that includes a [static] variable that can only be accessed by the task. You now create multiple instances of your task. Then you need a copy of that [static] variable for each task.
That's where your implementation could use Thread Local Storage. In other words, it is a static area of memory that gets copied for each thread in a program.
As an alternative to TLS, a thread could allocate such storage at the top of the stack.
We need thread-local storage to create libraries that have thread-safe functions, because of the thread-local storage each call to a function has its copy of the same global data, so it's safe I like to point out that the implementation is the same for copy on write technique.
in normal function with global data, the content of that data can be updated by multiple threads and make it unreliable, but in thread-local storage, you can think of it as
"global became local when multiple access happen "

D how to mark everything __gshared?

Is there any way to mark all objects __gshared with DMD? I am working on a game engine where pretty much everything needs to be shared between threads, and spamming __gshared or shared everywhere doesn't cut it.
For everyone wanting me not to do this: Critical sections will be minimal and reduced to checking if an enum is set to Loaded or not (mutexed of course). So concurrency won't gain me anything.
you can put all the variables in a block and declare that shared
__gshared{
SharedClass instance;
//...
}
also note that all fields in a shared class or struct are shared
I should however note that this inconvenience is by design and an encouragement to restructure your data to minimize the shared stuff
__gshared tells garbage collector that resource is may be used within external code, so you will need manually alloc/dealloc it(and so you can access the same resource in any thread), shared on the other hand is for actual multi-thread sharing.
though i may be wrong on some details, the actual idea is that

There is any limit on how many critical section i can create?

i have a Class that can be accessed on multiple thread.
To make sure i don't have simultaneous access i will use a CCriticalSection
I was wondering if i can just create a CCriticalSectionfor any copy of the object (i think i can have about 100-1000 this object in the program) or it will be best to create a static member CCriticalSection and use this for all the object?
Prior to XP/Server 2003 you could run out of kernel objects for CRITICAL_SECTIONs (specifically the event used to arbitrate when there was contention on the CRITICAL_SECTION). For XP and beyond you're bounded as you are for many things, by your virtual address space.
Surely there is a limit, but 1000 is perfectly fine.
But in your case I believe static member is better.
Creating extra objects is the last thing you should do from the performance prospective.
Windows has no limit on the number of sections you can create other than available memory (due to internal debug linkages, its consumes more than sizeof(CCriticalSection) or sizeof(CriticalSection).
If your scope was only to "signal" why not use InterlockedExchange and Interlock... family functions?

Is it ok to create shared variables inside a thread?

I think this might be a fairly easy question.
I found a lot of examples using threads and shared variables but in no example a shared variable was created inside a thread. I want to make sure I don't do something that seems to work and will break some time in the future.
The reason I need this is I have a shared hash that maps keys to array refs. Those refs are created/filled by one thread and read/modified by another (proper synchronization is assumed). In order to store those array refs I have to make them shared too. Otherwise I get the error Invalid value for shared scalar.
Following is an example:
my %hash :shared;
my $t1 = threads->create(
sub { my #ar :shared = (1,2,3); $hash{foo} = \#ar });
$t1->join;
my $t2 = threads->create(
sub { print Dumper(\%hash) });
$t2->join;
This works as expected: The second thread sees the changes the first made. But does this really hold under all circumstances?
Some clarifications (regarding Ian's answer):
I have one thread A reading from a pipe and waiting for input. If there is any, thread A will write this input in a shared hash (it maps scalars to hashes... those are the hashes that need to be declared shared as well) and continues to listen on the pipe. Another thread B gets notified (via cond_wait/cond_signal) when there is something to do, works on the stuff in the shared hash and deletes the appropriate entries upon completion. Meanwhile A can add new stuff to the hash.
So regarding Ian's question
[...] Hence most people create all their shared variables before starting any sub-threads.
Therefore even if shared variables can be created in a thread, how useful would it be?
The shared hash is a dynamically growing and shrinking data structure that represents scheduled work that hasn't yet been worked on. Therefore it makes no sense to create the complete data structure at the start of the program.
Also the program has to be in (at least) two threads because reading from the pipe blocks of course. Furthermore I don't see any way to make this happen without sharing variables.
The reason for a shared variable is to share. Therefore it is likely that you will wish to have more than one thread access the variable.
If you create your shared variable in a sub-thread, how will you stop other threads accessing it before it has been created? Hence most people create all their shared variables before starting any sub-threads.
Therefore even if shared variables can be created in a thread, how useful would it be?
(PS, I don’t know if there is anything in perl that prevents shared variables being created in a thread.)
PS A good design will lead to very few (if any) shared variables
This task seems like a good fit for the core module Thread::Queue. You would create the queue before starting your threads, push items on with the reader, and pop them off with the processing thread. You can use the blocking dequeue method to have the processing thread wait for input, avoiding the need for signals.
I don't feel good answering my own question but I think the answers so far don't really answer it. If something better comes along, I'd be happy to accept that. Eric's answer helped though.
I now think there is no problem with sharing variables inside threads. The reasoning is: Threads::Queue's enqueue() method shares anthing it enqueues. It does so with shared_clone. Since enqueuing should be good from any thread, sharing should too.

Resources