简体   繁体   中英

const pointer to struct containing a mutex

I have something like this:

typedef struct
{
    pthread_mutex_t mtx;
    /* Other stuff */
} some_struct_t;

void some_func (some_struct_t *s)
{
    pthread_mutex_lock (&s->mtx);
    /* Some stuff */
    pthread_mutex_unlock (&s->mtx);
}

some_func does not modify s , and I would like to change the signature to

void some_func (const some_struct_t *s);

but the calls to pthreads functions won't allow me to do that without warnings.

Is there any common idiom I could use to express that the some_struct_t will be logically constant inside the function?

Any way to use some_func from inside another function which has a const some_struct_t *s without doing a cast?

some_func modifies the mtx member, so it cannot be const.

But you can make mtx a pointer. You then still change the mutex, but that will no longer be covered by the const.

typedef struct
{
    pthread_mutex_t *mtx;
    /* Other stuff */
} some_struct_t;

void some_func(const some_struct_t *s)
{
    pthread_mutex_lock(s->mtx);
    /* Some stuff */
    pthread_mutex_unlock(s->mtx);
}

int main()
{
    pthread_mutex_t mtx = MUTEX_INITIALIZER;
    some_struct s = {
        .mtx = &mtx;
    };
    some_func(&s);
}

Now some_func no longer modifies s , but initializing a some_struct variable (and cleaning it up) has become a little bit more involved.

Expanding on koder's answer , you can have a redundant pointer inside some_struct_t to the same mutex , and use that instead of the address of the real mutex :

typedef struct
{
    pthread_mutex_t pmtx;
    pthread_mutex_t *mtx;
    /* Other stuff */
} some_struct_t;

void some_func (const some_struct_t *s)
{
    pthread_mutex_lock (s->mtx);
    /* Some stuff */
    pthread_mutex_unlock (s->mtx);
}

int main ()
{
    some_struct_t  s;

    pthread_mutex_init (&s.pmtx, NULL);
    s.mtx = &s.pmtx;
    some_func (&s);
    pthread_mutex_destroy (&s.pmtx);
}

Alternatively, you can trick the compiler by passing the pointer to the mutex in another parameter, and hide that implementation detail to the programmer/user with a macro:

#define some_func(a)      some_func_hidden (a, &(a)->mtx)

typedef struct
{
    pthread_mutex_t mtx;
    /* Other stuff */
} some_struct_t;

void some_func_hidden (const some_struct_t *s, pthread_mutex_t *mtx)
{
    pthread_mutex_lock (mtx);
    /* Some stuff */
    pthread_mutex_unlock (mtx);
}

int main ()
{
    some_struct_t  s;

    pthread_mutex_init (&s.mtx, NULL);
    some_func (&s);
    pthread_mutex_destroy (&s.mtx);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM