summaryrefslogtreecommitdiffstats
path: root/src/server/reference.c
blob: 64109ca39165a27845c20847c932c3b40f6fddfc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef unlikely
#define unlikely(x) (x)
#endif
#include "reference.h"
#include <stdio.h>
#include <stdlib.h>

void ref_init( ref *reference, void ( *freefun )( ref * ), long count )
{
	reference->count = count;
	reference->free = freefun;
}

_Noreturn void _ref_error( const char *message )
{
	fprintf( stderr, "%s\n", message );
	abort();
}

void ref_setref( weakref *weakref, ref *ref )
{
	union _aligned_ref_ *new_weakref = 0;
	if ( ref ) {
		( new_weakref = aligned_ref( ref->_aligned_ref ) )->ref = ref;
		ref->count += sizeof( union _aligned_ref_ ) + 1;
	}
	char *old_weakref = (char *)atomic_exchange( weakref, new_weakref );
	if ( !old_weakref )
		return;
	struct _ref_ *old_ref = aligned_ref( old_weakref )->ref;
	old_ref->count += old_weakref - (char *)aligned_ref( old_weakref ) - sizeof( union _aligned_ref_ );
	ref_put( old_ref );
}