75ba88322b71c6ff4cc1fedeb6e5f43822de800c
[sdk] / ecere / src / gfx / newFonts / cc / mmbitmap.h
1 /* *****************************************************************************
2  * Copyright (c) 2007-2014 Alexis Naveros.
3  *
4  * Ecere Corporation has unlimited/unrestricted rights.
5  * *****************************************************************************/
6 #include "cpuconfig.h"
7 #include "mm.h"
8
9 #if !defined(CPUCONF_LONG_BITSHIFT) || !defined(CPUCONF_LONG_BITS)
10  #error Preprocessor symbols CPUCONF_LONG_BITSHIFT and CPUCONF_LONG_BITS are undefined!
11  #error This header requires cpuconfig.h
12 #endif
13
14 #if !defined(MM_ATOMIC_SUPPORT)
15  #warning Compiling mmbitmap without atomic support, it is going to be SLOW.
16  #warning This header requires mm.h
17 #endif
18
19
20 typedef struct
21 {
22   size_t entrycount;
23   size_t mapsize;
24 #ifdef MM_ATOMIC_SUPPORT
25   mmAtomicL *map;
26 #else
27   long *map;
28   mtMutex mutex;
29 #endif
30 } mmBitMap;
31
32 int mmBitMapInit( mmBitMap *bitmap, size_t entrycount, int initvalue );
33 void mmBitMapReset( mmBitMap *bitmap, int resetvalue );
34 void mmBitMapResetRange( mmBitMap *bitmap, int minimumentrycount, int resetvalue );
35 void mmBitMapFree( mmBitMap *bitmap );
36
37 int mmBitMapFindSet( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex );
38 int mmBitMapFindClear( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex );
39
40
41 ////
42
43
44 /* No atomic locking, single-threaded access */
45
46 static inline int mmBitMapDirectGet( mmBitMap *bitmap, size_t entryindex )
47 {
48   int value;
49   size_t index, shift;
50   index = entryindex >> CPUCONF_LONG_BITSHIFT;
51   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
52 #ifdef MM_ATOMIC_SUPPORT
53   value = (int)(( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) >> shift ) & 0x1);
54 #else
55   value = ( bitmap->map[index] >> shift ) & 0x1;
56 #endif
57   return value;
58 }
59
60 static inline void mmBitMapDirectSet( mmBitMap *bitmap, size_t entryindex )
61 {
62   size_t index, shift;
63   index = entryindex >> CPUCONF_LONG_BITSHIFT;
64   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
65 #ifdef MM_ATOMIC_SUPPORT
66   MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) |= (long)1 << shift;
67 #else
68   bitmap->map[index] |= (long)1 << shift;
69 #endif
70   return;
71 }
72
73 static inline void mmBitMapDirectClear( mmBitMap *bitmap, size_t entryindex )
74 {
75   size_t index, shift;
76   index = entryindex >> CPUCONF_LONG_BITSHIFT;
77   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
78 #ifdef MM_ATOMIC_SUPPORT
79   MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) &= ~( (long)1 << shift );
80 #else
81   bitmap->map[index] &= ~( (long)1 << shift );
82 #endif
83   return;
84 }
85
86 static inline int mmBitMapDirectMaskGet( mmBitMap *bitmap, size_t entryindex, long mask )
87 {
88   int value;
89   size_t index, shift;
90   index = entryindex >> CPUCONF_LONG_BITSHIFT;
91   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
92 #ifdef MM_ATOMIC_SUPPORT
93   value = (int)(( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) >> shift ) & mask);
94 #else
95   value = ( bitmap->map[index] >> shift ) & mask;
96 #endif
97   return value;
98 }
99
100 static inline void mmBitMapDirectMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask )
101 {
102   size_t index, shift;
103   index = entryindex >> CPUCONF_LONG_BITSHIFT;
104   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
105 #ifdef MM_ATOMIC_SUPPORT
106   MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) = ( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) & ~( mask << shift ) ) | ( value << shift );
107 #else
108   bitmap->map[index] = ( bitmap->map[index] & ~( mask << shift ) ) | ( value << shift );
109 #endif
110   return;
111 }
112
113
114 ////
115
116
117 /* Atomic locking, multi-threaded access */
118
119 static inline int mmBitMapGet( mmBitMap *bitmap, size_t entryindex )
120 {
121   int value;
122   size_t index, shift;
123   index = entryindex >> CPUCONF_LONG_BITSHIFT;
124   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
125 #ifdef MM_ATOMIC_SUPPORT
126   value = (int)(( mmAtomicReadL( &bitmap->map[index] ) >> shift ) & 0x1);
127 #else
128   mtMutexLock( &bitmap->mutex );
129   value = ( bitmap->map[index] >> shift ) & 0x1;
130   mtMutexUnlock( &bitmap->mutex );
131 #endif
132   return value;
133 }
134
135 static inline void mmBitMapSet( mmBitMap *bitmap, size_t entryindex )
136 {
137   size_t index, shift;
138   index = entryindex >> CPUCONF_LONG_BITSHIFT;
139   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
140 #ifdef MM_ATOMIC_SUPPORT
141  #ifdef BP_BITMAP_PREWRITE_CHECK
142   if( !( mmAtomicReadL( &bitmap->map[index] ) & ( (long)1 << shift ) ) )
143     mmAtomicOrL( &bitmap->map[index], (long)1 << shift );
144  #else
145   mmAtomicOrL( &bitmap->map[index], (long)1 << shift );
146  #endif
147 #else
148   mtMutexLock( &bitmap->mutex );
149   bitmap->map[index] |= (long)1 << shift;
150   mtMutexUnlock( &bitmap->mutex );
151 #endif
152   return;
153 }
154
155 static inline void mmBitMapClear( mmBitMap *bitmap, size_t entryindex )
156 {
157   size_t index, shift;
158   index = entryindex >> CPUCONF_LONG_BITSHIFT;
159   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
160 #ifdef MM_ATOMIC_SUPPORT
161  #ifdef BP_BITMAP_PREWRITE_CHECK
162   if( mmAtomicReadL( &bitmap->map[index] ) & ( (long)1 << shift ) )
163     mmAtomicAndL( &bitmap->map[index], ~( (long)1 << shift ) );
164  #else
165   mmAtomicAndL( &bitmap->map[index], ~( (long)1 << shift ) );
166  #endif
167 #else
168   mtMutexLock( &bitmap->mutex );
169   bitmap->map[index] &= ~( (long)1 << shift );
170   mtMutexUnlock( &bitmap->mutex );
171 #endif
172   return;
173 }
174
175 static inline int mmBitMapMaskGet( mmBitMap *bitmap, size_t entryindex, long mask )
176 {
177   int value;
178   size_t index, shift;
179   index = entryindex >> CPUCONF_LONG_BITSHIFT;
180   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
181 #ifdef MM_ATOMIC_SUPPORT
182   value = (int)(( mmAtomicReadL( &bitmap->map[index] ) >> shift ) & mask);
183 #else
184   mtMutexLock( &bitmap->mutex );
185   value = ( bitmap->map[index] >> shift ) & mask;
186   mtMutexUnlock( &bitmap->mutex );
187 #endif
188   return value;
189 }
190
191 static inline void mmBitMapMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask )
192 {
193   size_t index, shift;
194   long oldvalue, newvalue;
195   index = entryindex >> CPUCONF_LONG_BITSHIFT;
196   shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
197 #ifdef MM_ATOMIC_SUPPORT
198   for( ; ; )
199   {
200     oldvalue = (int)mmAtomicReadL( &bitmap->map[index] );
201     newvalue = ( oldvalue & ~( mask << shift ) ) | ( value << shift );
202     if( mmAtomicCmpReplaceL( &bitmap->map[index], oldvalue, newvalue ) )
203       break;
204   }
205 #else
206   mtMutexLock( &bitmap->mutex );
207   bitmap->map[index] = ( bitmap->map[index] & ~( mask << shift ) ) | ( value << shift );
208   mtMutexUnlock( &bitmap->mutex );
209 #endif
210   return;
211 }