# SLIST_FOREACH and SLIST_FOREACH_SAFE



## bsd_newbie (Feb 28, 2009)

Please correct me if I am wrong,

As long as you are only walking the list and not doing element insertions and deletions SLIST_FOREACH is fine. Only if one is deleting or adding elements while walking the list, one needs to use SLIST_FOREACH_SAFE ?

thanks.


----------



## Mel_Flynn (Feb 28, 2009)

You can add, the list isn't affected by it. Problem with deletion is that you invalidate the current pointer, and as such the next invocation of the loop dereferences that pointer to get SLIST_NEXT.
SLIST_FOREACH_SAFE already stores SLIST_NEXT in temp_var and simply copies that pointer to var on the next invocation.


----------



## bsd_newbie (Feb 28, 2009)

Basically in my code I have couple of posix style threads (created using pthreads) that manipulate the singaly linked lists. There is also a thread that walks the list to print the number of elements in the list. 

I am using SLIST_FOREACH in the walker thread and SLIST_FOREACHSAFE in the deletion thread and also in the addition thread.

Now a related question - So far my code is working accidently as I am not using mutexes to keep the list consistent. Now I do understand that I need to use pthread_mutex_lock before adding and also before deleting any elements in the list, but do I need a lock before walking the list to just count the number of elements in it.


----------



## Mel_Flynn (Mar 8, 2009)

Yes. * _FOREACH_SAFE is only safe in the current thread, concurrently, you can still invalidate that pointer.

A better approach if you just want the count is to put the current count in a struct along with the SLIST_HEAD, like:

```
typedef struct _mylist
{
    size_t cnt;
    /* optional, see below */
    pthread_rwlock_t rwl;
    SLIST_HEAD(, entry) head;
}
```

If you care about the accuracy of cnt, then use the read-write lock. On insert/delete first obtain the rwlock with pthread_rwlock_wrlock, update cnt and release. When reading cnt, use pthread_rwlock_rdlock, tryrdlock if you don't want to wait and implement your own spinlock, timedrdlock if you want to try to get an accurate value for a little while, but if it can't be obtained, just read the inaccurate value.


----------

