my_bitmap.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Handling of uchar arrays as large bitmaps.
  15.   API limitations (or, rather asserted safety assumptions,
  16.   to encourage correct programming)
  17.     * the size of the used bitmap is less than ~(uint) 0
  18.     * it's a multiple of 8 (for efficiency reasons)
  19.     * when arguments are a bitmap and a bit number, the number
  20.       must be within bitmap size
  21.     * bitmap_set_prefix() is an exception - one can use ~0 to set all bits
  22.     * when both arguments are bitmaps, they must be of the same size
  23.     * bitmap_intersect() is an exception :)
  24.       (for for Bitmap::intersect(ulonglong map2buff))
  25.   TODO:
  26.   Make assembler THREAD safe versions of these using test-and-set instructions
  27. */
  28. #include "mysys_priv.h"
  29. #include <my_bitmap.h>
  30. #include <m_string.h>
  31. static inline void bitmap_lock(MY_BITMAP* map)
  32. {
  33. #ifdef THREAD
  34.   if (map->mutex)
  35.     pthread_mutex_lock(map->mutex);
  36. #endif
  37. }
  38. static inline void bitmap_unlock(MY_BITMAP* map)
  39. {
  40. #ifdef THREAD
  41.   if (map->mutex)
  42.     pthread_mutex_unlock(map->mutex);
  43. #endif
  44. }
  45. my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size,
  46.     my_bool thread_safe)
  47. {
  48.   DBUG_ENTER("bitmap_init");
  49.   DBUG_ASSERT((bitmap_size & 7) == 0);
  50.   bitmap_size/=8;
  51.   if (!(map->bitmap=buf) &&
  52.       !(map->bitmap= (uchar*) my_malloc(bitmap_size +
  53. (thread_safe ?
  54.  sizeof(pthread_mutex_t) : 0),
  55. MYF(MY_WME | MY_ZEROFILL))))
  56.     return 1;
  57.   map->bitmap_size=bitmap_size;
  58. #ifdef THREAD
  59.   if (thread_safe)
  60.   {
  61.     map->mutex=(pthread_mutex_t *)(map->bitmap+bitmap_size);
  62.     pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST);
  63.   }
  64.   else
  65.     map->mutex=0;
  66. #endif
  67.   DBUG_RETURN(0);
  68. }
  69. void bitmap_free(MY_BITMAP *map)
  70. {
  71.   DBUG_ENTER("bitmap_free");
  72.   if (map->bitmap)
  73.   {
  74. #ifdef THREAD
  75.     if (map->mutex)
  76.       pthread_mutex_destroy(map->mutex);
  77. #endif
  78.     my_free((char*) map->bitmap, MYF(0));
  79.     map->bitmap=0;
  80.   }
  81.   DBUG_VOID_RETURN;
  82. }
  83. void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
  84. {
  85.   DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
  86.   bitmap_lock(map);
  87.   bitmap_fast_set_bit(map, bitmap_bit);
  88.   bitmap_unlock(map);
  89. }
  90. uint bitmap_set_next(MY_BITMAP *map)
  91. {
  92.   uchar *bitmap=map->bitmap;
  93.   uint bit_found = MY_BIT_NONE;
  94.   uint bitmap_size=map->bitmap_size*8;
  95.   uint i;
  96.   DBUG_ASSERT(map->bitmap);
  97.   bitmap_lock(map);
  98.   for (i=0; i < bitmap_size ; i++, bitmap++)
  99.   {
  100.     if (*bitmap != 0xff)
  101.     { /* Found slot with free bit */
  102.       uint b;
  103.       for (b=0; ; b++)
  104.       {
  105. if (!(*bitmap & (1 << b)))
  106. {
  107.   *bitmap |= 1<<b;
  108.   bit_found = (i*8)+b;
  109.   break;
  110. }
  111.       }
  112.       break; /* Found bit */
  113.     }
  114.   }
  115.   bitmap_unlock(map);
  116.   return bit_found;
  117. }
  118. void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit)
  119. {
  120.   DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
  121.   bitmap_lock(map);
  122.   bitmap_fast_clear_bit(map, bitmap_bit);
  123.   bitmap_unlock(map);
  124. }
  125. void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
  126. {
  127.   uint prefix_bytes, prefix_bits;
  128.   DBUG_ASSERT(map->bitmap &&
  129.       (prefix_size <= map->bitmap_size*8 || prefix_size == (uint) ~0));
  130.   bitmap_lock(map);
  131.   set_if_smaller(prefix_size, map->bitmap_size*8);
  132.   if ((prefix_bytes= prefix_size / 8))
  133.     memset(map->bitmap, 0xff, prefix_bytes);
  134.   if ((prefix_bits= prefix_size & 7))
  135.     map->bitmap[prefix_bytes++]= (1 << prefix_bits)-1;
  136.   if (prefix_bytes < map->bitmap_size)
  137.     bzero(map->bitmap+prefix_bytes, map->bitmap_size-prefix_bytes);
  138.   bitmap_unlock(map);
  139. }
  140. void bitmap_clear_all(MY_BITMAP *map)
  141. {
  142.   bitmap_set_prefix(map, 0);
  143. }
  144. void bitmap_set_all(MY_BITMAP *map)
  145. {
  146.   bitmap_set_prefix(map, ~0);
  147. }
  148. my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size)
  149. {
  150.   uint prefix_bits= prefix_size & 7, res= 0;
  151.   uchar *m= map->bitmap, *end_prefix= map->bitmap+prefix_size/8,
  152.         *end= map->bitmap+map->bitmap_size;
  153.   DBUG_ASSERT(map->bitmap && prefix_size <= map->bitmap_size*8);
  154.   bitmap_lock((MY_BITMAP *)map);
  155.   while (m < end_prefix)
  156.     if (*m++ != 0xff)
  157.       goto ret;
  158.   if (prefix_bits && *m++ != (1 << prefix_bits)-1)
  159.     goto ret;
  160.   while (m < end)
  161.     if (*m++ != 0)
  162.       goto ret;
  163.   res=1;
  164. ret:
  165.   bitmap_unlock((MY_BITMAP *)map);
  166.   return res;
  167. }
  168. my_bool bitmap_is_clear_all(const MY_BITMAP *map)
  169. {
  170.   return bitmap_is_prefix(map, 0);
  171. }
  172. my_bool bitmap_is_set_all(const MY_BITMAP *map)
  173. {
  174.   return bitmap_is_prefix(map, map->bitmap_size*8);
  175. }
  176. my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit)
  177. {
  178.   DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
  179.   return bitmap_fast_is_set(map, bitmap_bit);
  180. }
  181. my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
  182. {
  183.   uint res=0;
  184.   uchar *m1=map1->bitmap, *m2=map2->bitmap, *end;
  185.   DBUG_ASSERT(map1->bitmap && map2->bitmap &&
  186.               map1->bitmap_size==map2->bitmap_size);
  187.   bitmap_lock((MY_BITMAP *)map1);
  188.   bitmap_lock((MY_BITMAP *)map2);
  189.   end= m1+map1->bitmap_size;
  190.   while (m1 < end)
  191.   {
  192.     if ((*m1++) & ~(*m2++))
  193.       goto ret;
  194.   }
  195.   res=1;
  196. ret:
  197.   bitmap_unlock((MY_BITMAP *)map2);
  198.   bitmap_unlock((MY_BITMAP *)map1);
  199.   return res;
  200. }
  201. my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
  202. {
  203.   uint res;
  204.   DBUG_ASSERT(map1->bitmap && map2->bitmap &&
  205.               map1->bitmap_size==map2->bitmap_size);
  206.   bitmap_lock((MY_BITMAP *)map1);
  207.   bitmap_lock((MY_BITMAP *)map2);
  208.   res= memcmp(map1->bitmap, map2->bitmap, map1->bitmap_size)==0;
  209.   bitmap_unlock((MY_BITMAP *)map2);
  210.   bitmap_unlock((MY_BITMAP *)map1);
  211.   return res;
  212. }
  213. void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
  214. {
  215.   uchar *to=map->bitmap, *from=map2->bitmap, *end;
  216.   uint len=map->bitmap_size, len2=map2->bitmap_size;
  217.   DBUG_ASSERT(map->bitmap && map2->bitmap);
  218.   bitmap_lock(map);
  219.   bitmap_lock((MY_BITMAP *)map2);
  220.   end= to+min(len,len2);
  221.   while (to < end)
  222.     *to++ &= *from++;
  223.   if (len2 < len)
  224.   {
  225.     end+=len-len2;
  226.     while (to < end)
  227.       *to++=0;
  228.   }
  229.   bitmap_unlock((MY_BITMAP *)map2);
  230.   bitmap_unlock(map);
  231. }
  232. void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
  233. {
  234.   uchar *to=map->bitmap, *from=map2->bitmap, *end;
  235.   DBUG_ASSERT(map->bitmap && map2->bitmap &&
  236.               map->bitmap_size==map2->bitmap_size);
  237.   bitmap_lock(map);
  238.   bitmap_lock((MY_BITMAP *)map2);
  239.   end= to+map->bitmap_size;
  240.   while (to < end)
  241.     *to++ &= ~(*from++);
  242.   bitmap_unlock((MY_BITMAP *)map2);
  243.   bitmap_unlock(map);
  244. }
  245. void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
  246. {
  247.   uchar *to=map->bitmap, *from=map2->bitmap, *end;
  248.   DBUG_ASSERT(map->bitmap && map2->bitmap &&
  249.               map->bitmap_size==map2->bitmap_size);
  250.   bitmap_lock(map);
  251.   bitmap_lock((MY_BITMAP *)map2);
  252.   end= to+map->bitmap_size;
  253.   while (to < end)
  254.     *to++ |= *from++;
  255.   bitmap_unlock((MY_BITMAP *)map2);
  256.   bitmap_unlock(map);
  257. }