This is my struct:
struct example {
int c=0;
char buf[10];
}
I have a struct of this type allocated in main()
...
struct example *ex=malloc(sizeof(*ex));
...
and passed to a thread by
...
pthread_create(&id[i], NULL, t_func, ex);
...
pthread_create is called into a child of main.
t_func is:
void *t_func(void* args) {
struct example *extmp = args;
....
How can I create a local struct example in every thread and copy into it the struct and the values of args? I need it such that if I modify a field of the local struct, that will not be seen in other threads. I've seen other similar questions, but I haven't found my answer...
In C you can assign objects of structure type:
struct example *extmp = args;
struct example local_copy = *extmp;
If you want a clean, unshared copy for each thread, the place to make the copy is before passing it to the thread. This avoids issues with needing to lock the data.
In your case, the main function should malloc another struct, then you can use memcpy or *new_data = *old_data to copy the data. Then you pass the pointer into the thread.
Now this is the important part. The main thread should never touch that copy again. The thread should call free when it is done using the data.
Yes, this means that you still have a pointer to a struct and not a struct on the thread stack. However, think about it: what does a struct on the stack get you? You have to type -> instead of . and that's about it.
Of course, my advice gets a lot more complicated and develops exceptions and curlicues if you are doing memory allocation with lock-free per-thread pools or NUMA. In those cases you probably do want to make the copy inside the thread. The main data will need to be locked and the thread will need to make its copy then unlock the data source.
In some exciting case you may need three copies: the primary copy (main memory), a temporary copy (main memory but no need to lock the primary) and the in-thread copy (now in per-thread memory, also no locks).
Related
I have to create for academic purpose an "On-Demand Server" that is based on the TCP protocol. The client each time sends a KEY and a VALUE that I have to store them in a global struct like the one bellow:
I use a function named "put" to store every KEY and VALUE to the struct and a "get" function that uses the key and finds the correct value:
My problem is that if a client makes a change in the struct the next one won't be able to know. I used semaphores in order to make the server wait until the child finishes and then accept the next child but I have still the same problem.
I read that I have to make the memory of this struct shared in order to make this work using mmaps but still I can't find a proper solution.
I make my first steps in server programming and every help would be great.
My problem is that if a client makes a change in the struct the next one won't be able to know.
As you noted, mmap() is part of the solution...
Shared memory needs of your application can be addressed with _shm_open()_, _shm_unlink()_, mmap etc. as illustrated in this post. And here for additional examples on shared memory
All of the essentials are summarized in the links, but this excerpt describes the basic concept:
shm_open() creates and opens a new, or opens an existing, POSIX
shared memory object. A POSIX shared memory object is in effect a
handle which can be used by unrelated processes to mmap(2) the same
region of shared memory. The shm_unlink() function performs the
converse operation, removing an object previously created by
shm_open().
I also wanted to suggest that dynamic allocation of memory may be of use in creating space for your struct on an as-needed basis. The size of members, as shown are excessively large,
char keys[4096];
char values[4096];
but in comments you state they only need to be 51 bytes. The struct then can be created as a typedef:
struct keyvalue {
char keys[51];
char values[51];
} DATA;
The create an instance of a pointer to your struct:
DATA *pData = {0};
Which can then be sized on an as needed basis using standard malloc, and or realloc
pData = malloc(initialSize*sizeof(DATA));
As size requirements change, use the following to grow memory:
DATA *tmp = {0};
tmp = realloc(pData, newSize);
if(!tmp) return -1;//ensure memory allocation successful
pData = tmp;//tmp includes previous contents of pData, and more space
... //continue using pData
Free pData when it is no longer needed.
free(pData);
To pass this struct in a function, the function might look like this:
void func1(DATA *d, int numElements)
{
...
for(i=0;i<numElements;i++)
{
strcpy(d[i]->keys, "some key");
strcpy(d[i]->values, "some value");
}
...
}
To call that function with a copy of pData, if say it had a 1000 elements:
func1(pData, 1000);
I'm writing a very simple code in which i need to use some threads.
When I create first type of thread i pass argument with pthread_create:
fman thread_arg;
thread_arg.sd=sda;
char* split = strtok(buffer, "|");
thread_arg.wcount=atoi(split);
split = strtok(NULL,"");
strcpy(thread_arg.id, split);
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
And everything works fine, but in function registerF I need to do something like this:
wman thread_arg;
thread_arg.sd=foremans_fd[ix];
thread_arg.fmanix=ix;
strcpy(thread_arg.id,tmpr);
pthread_create(&thread_temp, NULL, registerW, &thread_arg);
Those arguments are structures defined by me:
typedef struct fman
{
int sd;
char id[100];
int wcount;
} fman;
typedef struct wman
{
int sd;
int fmanix;
char id[100];
} wman;
And when I check it by printf("%x, args) I get the same address but values are different inside. Where is my mistake?
One likely problem is here:
fman thread_arg;
[...]
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
Note that the thread_arg object is located on the stack, and thus will be destroyed (and likely overwritten by other stack variables) when the function it is declared in returns.
pthread_create(), on the other hand, launches a thread that will run asynchronously with this function, which means that the thread can (and often will) run after the function you excerpted has returned, which means that by the time the thread dereferences &thread_arg, thread_arg has likely already been destroyed and that pointer is now pointing to some other data that was written into the same stack location later on.
Unless you are doing something special to make sure that the struct's lifetime is long enough to include all of the spawned thread's accesses to the struct, then the fact that this code ever works is pure luck (i.e. the scheduler just happened to schedule the thread to run and perform all of its accesses to the struct before the struct was destroyed/overwritten). You definitely can't depend on that.
In order to fix the problem, you need to either allocate the struct on the heap (so that it won't be destroyed when the function returns -- the spawned thread can then free the struct when it is done using it), or use some kind of synchronization mechanism (e.g. a condition variable) to cause the main thread to block inside your function until the spawned thread has indicated that it is done accessing the struct.
The thread struct in the running thread is treated like a block of memory and accessed using offsets. Since your fman and wman structs have different orders (4+100+4) vs (4+4+100), it's likely that you're getting right struct but reading from different memory location, given the passed struct to this thread is fman, and it's being accessed as wman.
Try changing them both to same signature, as in, int, int, char* and it should work.
I have a question about passing a struct to a function without declaring the struct first.
I have a function that takes a struct pointer like this:
static void DrawArc(struct MATH_POINT *p, other args);
I know I can pass a structure like this
struct MATH_POINT point = {0,0};
DrawArc(&point, other args);
But I can also do it like this:
DrawArc(&(struct MATH_POINT){0,0}, other args);
I am doing it this way because I am on an embedded platform with very limited register space, and my GUI functions require many arguments.
But my worry is that the structures I initialized in the argument list will stick around and use up RAM. Is this possible? Or will the struct be destroyed as soon as the function finishes?
Thanks!
You are mixing and matching things. Any object which is not explicitly instantiated with malloc/calloc/etc but it is instantiated locally won't take any heap memory, it will just make the stack grow until the variable exits the scope.
Your first example:
struct MATH_POINT point = {0,0};
DrawArc(&point, other args);
is perfectly fine. point will be allocated on stack, it won't take more memory than the one needed to store itself and it will be automatically released upon exiting the scope of declaration.
In any case, in both your examples, since there is no dynamic allocation, there's no risk of leaving things around.
struct MATH_POINT point = {0,0};
DrawArc(&point, other args);
this point variable will live longer than this
DrawArc(&(struct MATH_POINT){0,0}, other args);
since the first one's scope is still alive after calling DrawArc, while the second is discarded as soon as the function returns. (and: Neither of them "stick around", both have a well defined lifecycle ;-) )
if you want to "remove" a variable, add an additional scope, and close it if you don't need it anymore:
#define MANY 10000
{
struct MATH_POINT removeMe[MANY];
/* work on removeMe while they're alive */
doThings(removeMe, other_stuff);
}
/* here removeMe is gone, and the mem can/will be used otherwise */
I'm trying to make a list of pointers to a structure called "thread". Here is my attempt:
//kmalloc is my malloc, don't worry
struct thread **process0 = kmalloc(sizeof(struct *thread));
//^ This line is giving me a parse error
And basically I want process0[0] to be a pointer to a thread,
process0[1] to be a pointer to another thread,
process0[2] to be a pointer to yet another thread,
etc.
Later I may want to access one of the thread's "addrspace" member (a pointer to an addrspace structure) along the following:
struct addrspace *test = process0[i][j]->addrspace;
Where I'm thinking proccess0[i] is a particular list of thread pointers, and process0[i][j] is a particular thread pointer from the particular list of thread pointers... Then I'd want to access one of its members via the -> operator.
I've always sucked at pointer arithmetic stuff and would like to get things cleared up. Thank you very much.
The datatype that you want is "pointer to struct thread", or:
struct thread **process0 = kmalloc(sizeof(struct thread *));
struct thread **process0 = kmalloc(sizeof(struct * thread)*NUM_THREADS*NUM_PROCESSES_IN_EACH_THREAD); //kmalloc is my malloc, don't worry
Before you were only allocating like one pointer, if I read it right. Does this help at all?
Ok I have a struct defined as such...
typedef struct
{
enum COMMAND command;
enum CMD_SOURCE source;
CHAR parameters[16];
} focuserCommand;
I am trying to make a function that will add an instance of this type of struct to an array of focuserCommands. The array is defined like this...
extern focuserCommand CommandBuffer[CMD_BUFFER_SIZE];
the function I am trying to write should take a pointer to a focuserCommand and add it to CommandBuffer. I am implementing CommandBuffer as a FIFO ring buffer so I know i need to move the tail forwared so that my other functions can see that the buffer contains data. CmdBuffHead and CmdBuffTail represent the read and write pointers of the buffer. Writes are added to the tail, reads are made from the head.
void AddCmdToBfr( focuserCommand * cmd )
{
// What goes here to add the struct pointed to by cmd to
// element CmdBuffTail of the buffer?
CmdBuffTail++;
}
Given that you have the variable CmdBuffTail pointing at the next element of CommandBuffer to be written to, then:
void AddCmdToBfr(focusCommand *cmd)
{
assert(CmdBuffTail >= 0 && CmdBuffTail < CMD_BUFFER_SIZE);
CommandBuffer[CmdBuffTail++] = *cmd;
if (CmdBuffTail >= CMD_BUFFER_SIZE)
CmdBuffTail = 0;
}
This preserves the invariant that you need - that the index is in the range 0..CMD_BUFFER_SIZE-1.
You may also need a separate index (CmdBuffHead perhaps) to identify where to read from. If so, you would probably need to alter that value in AddCmdToBfr() if CmdBuffTail if catches up with it.
After fixing a goof copying the incoming command, it occurs to me that you need to think carefully about the memory management. In this case, your focususerCommand structure is simple enough (unless the typedef CHAR hides a pointer - in which case, slap wrists; don't hide pointers) that you can simply copy it with impunity. If you can't copy the structure simply (because it contains pointers to allocated memory), then you need to ensure you understand who owns the data to make sure that (a) any allocated memory is released, and (b) any allocated memory is released just once. This would mean, for example, that instead of just copying the new command over the old, you would have to first release the memory allocated to the old entry. Think in terms of C++ copy constructors and destructors - in C.