godo
godo

Reputation: 335

Sharing dynamically-allocated char * between threads

My application has two threads (thread A and thread B) that read and write from/to a global structure like the following:

struct global_data_s {
    pthread_mutex_t mutex;
    uint8_t a;
    char *string;
}

Thread A writes to global_data_s through a function:

set_global_data(struct global_data_s *in);

which sets the global structure according to the input global_data_s *in passed to the function (which manages the mutex lock/unlock mechanism).

Thread B reads from global_data_s with:

get_global_data(struct global_data_s *out);

This works as expected for static data (like uint8_t a), since the actual global data is only accessible by the get/set functions, and threads can freely work on a copy of the global data structure (the set function passes a local copy of the structure allocated in thread A and overwrites the global structure, while the get function returns a copy of the global data to a local struct in thread B. Everything is protected by mutex lock/unlock mechanism).

I found myself in a bit of a pickle, though, since string is allocated dynamically (via malloc) by thread A and contains a json-formatted string that is constantly updated (e.g. every second). Thread B is actually a webserver, that needs to get string and send it as soon as a GET request is made (this action should be performed for every incoming GET request).

I fear the whole "work on a copy of the global shared structure" fails here, since dynamic memory is involved.

My point is, when and where should I free the allocated string? Freeing the local copy of string obviously frees the shared global structure too (since both pointers point to the same address).

I hope I made myself clear, but please, feel free to ask if anything is unclear.

Thank you in advance.

Upvotes: 1

Views: 241

Answers (1)

ryyker
ryyker

Reputation: 23208

When architecturally feasible global variables and threading are not good bedfellows. But when forced to use them together, the global becomes a shared resource that can only be used by one thread at a time. It then becomes a simple matter of writing code that allows the threads to play nicely with each other, and share.
Enter mutex. (or some other thread safety device.)
In this case, you are using mutex. Each thread must wait for ownership of the mutex before it can execute the code that accesses the shared resource. With that in mind, each event that requires a thread to gain access to this global struct member, whether to read or to write, must first test the mutex to see if it is already being used by another thread. If not, take ownership, use the resource, release ownership. If it is already owned, it is the responsibility of the calling code to have a try-again method, that persists attempts to access until the mutex is free. When free, again, take ownership, use the resource, release ownership.

Upvotes: 1

Related Questions