0

Consider the following situation in a C program. We have a set of functions, let the generic one be

 void needs_param (void * param, ...);

, which depend on the value of some parameter param. The argument param is computed by a function, e.g.

 void compute_param (..., void * param); 

We would like to hide the details of the param (type, size, value, ...) to a caller as much as possible, where the caller is a function that makes use of the functions compute_param and needs_param. How to implement this most efficiently and thread-safe, if you are free to modify both needs_param and compute_param?

I have considered and excluded the following possibilities:

a: Because we are free to modify needs_param, one way to do that would be to pass gen_param and its arguments instead of the param, and let the needs_param compute param by itself. But param is expensive to compute and it is needed several times as the argument to other functions.

b: We could implement compute_param as

void * compute_param (...) {
    static param_type param = ...
    return &param;
}

However, this is not thread-safe, using openmp we would have to protect the call

#pragama omp critical
{
    void * param = compute_param (...)
}

which would severely affect the performance in a threaded program.

C: One solution would use malloc/free

void compute_param (..., void * param) {
    param = malloc (sizeof (param_type));
    ....
    *param = ...
}   

which burdens the caller with the freeing of the allocated memory, while being inefficient because of the expensive heap memory.

d: Use of alloca, e.g.

void * param = alloca (param_size);
compute_param (..., param);
...
needs_param (param, ...);

, needs the information about the param size in the caller space, which we would prefer to hide.

Do you have any suggestion?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

1 Answers1

3

I would recommend you to use a solution known as "opaque pointers". It is for example widely used in the Windows kernel world to hide objects from callers.

You first define a pointer type like typedef void* pobject;.

Then, you only manipulate your object that way in your program. A bunch of functions like pobject create_object(), use_object(pobject) and free_object(pobject) use this technique.

To ensure your object can be safely manipulated, add a mutex in the object itself. You can also add as first member, the size of the object to perform a quick check of the nature of the object (has it been manipulated by someone else?).

Then, in the functions, you really define your object like typedef struct { } object_int, *pobject_int. And in every function that manipulates it, just cast your opaque pointer from pobject to a pobject_int.

It indeed forces you to use the heap, but that's the most suitable solution if you don't want to share any information about your object with the callers.

jopasserat
  • 5,721
  • 4
  • 31
  • 50
Heis Spiter
  • 351
  • 3
  • 12
  • [Here is one example of opaque type](http://stackoverflow.com/questions/13032015/how-to-implement-a-class-in-c/13032531#13032531), using dynamic memory allocation. – Lundin Jan 16 '13 at 12:39