@@ -196,6 +196,24 @@ size_t fc_pool_record_now(fc_pool_t *pool)
196196}
197197
198198//+********************************* 内存块状态管理及链式操作 **********************************/
199+ /**
200+ * @brief 获取当前(链式)内存块已使用大小
201+ *
202+ * @param ptr 当前内存块地址
203+ * @return size_t
204+ */
205+ size_t fc_pool_used_size (void * ptr )
206+ {
207+ fc_assert (ptr != NULL );
208+ fc_pool_header_t * node = fc_pool_rewind_header (ptr ); // 从ptr指向的内存块开始,返回内存块头部地址
209+ size_t used_size = 0 ;
210+ while (node )
211+ {
212+ used_size += node -> used_size ;
213+ node = node -> next ;
214+ }
215+ return used_size ;
216+ }
199217
200218/**
201219 * @brief 标记当前内存块已使用大小
@@ -676,7 +694,7 @@ void fc_pool_free(fc_pool_t *pool, void *ptr)
676694
677695 // 开始合并到空闲链表
678696 {
679- after = NULL ;
697+ // after = NULL;
680698 prev = NULL ;
681699 prev_first = NULL ;
682700 FC_ATOMIC_SCOPE
@@ -961,109 +979,158 @@ void *fc_pool_realloc(fc_pool_t *pool, void *ptr, size_t size)
961979 {
962980 need_count = (int32_t )(((size + sizeof (fc_pool_header_t ) + node_size - 1 ) / node_size ) - node -> block_count ); // 还需要多少个连续内存块
963981
964- if (1 == need_count ) // 只需要一个内存块
982+ if (0 == need_count ) // 当前链上还有空闲内存仅仅修改标记大小
983+ {
984+ // 保持不变,仅仅修改标记大小
985+ fc_pool_mark_used (ptr , size ); // 标记实际使用大小
986+ return ptr ;
987+ }
988+ else if (need_count < 0 ) // 还要释放部分内存,正常使用比较少
965989 {
966- node = (fc_pool_header_t * )((uint8_t * )node + node -> block_count * node_size ); // 直接定位到需要取出的内存块第一个节点位置
990+ node = (fc_pool_header_t * )((uint8_t * )node - ( node -> block_count + need_count ) * node_size ); // 定位到需要释放的内存块第一个节点位置
967991 {
968- FC_ATOMIC_SCOPE
992+ node -> next = NULL ; // 释放的内存块下一个节点指向NULL
993+ node -> link_flag = FC_POOL_TAG_END ;
994+ node -> block_count = (- need_count );
995+ node -> used_size = node -> block_count * node_size - sizeof (fc_pool_header_t );
996+ }
997+ ret_ptr = fc_pool_skip_header (node );
998+ fc_pool_free (pool , ret_ptr );
999+ ret_ptr = ptr ; // 赋值用于下面判断realloc是否完成
1000+ }
1001+ else if (pool -> sort_free_enable )
1002+ {
1003+ if (1 == need_count ) // 只需要一个内存块
1004+ {
1005+ node = (fc_pool_header_t * )((uint8_t * )node + node -> block_count * node_size ); // 直接定位到需要取出的内存块第一个节点位置
9691006 {
970- // 遍历空闲链表看需要取出的内存块是否还在空闲链表中
971- node_free = pool -> list_free .next ;
972- node_prev = & (pool -> list_free );
973- while (node_free ) // 最坏O(n)
1007+ FC_ATOMIC_SCOPE
9741008 {
975- if ((size_t )node_free == (size_t )node ) // 链式内存是按顺序排列的,如果这块内存还未使用必定是一块链的起始
1009+ // 遍历空闲链表看需要取出的内存块是否还在空闲链表中
1010+ node_free = pool -> list_free .next ;
1011+ node_prev = & (pool -> list_free );
1012+ while (node_free ) // 最坏O(n)
9761013 {
977- // 找到这块内存了
978- node_prev -> next = node_free -> next ; // 从空闲链表中移除
979-
980- if (node_free -> linear_last != node_free ) // 非自旋节点,证明下一个节点跟这个节点是连续的(一定存在下一个节点)
1014+ if ((size_t )node_free == (size_t )node ) // 链式内存是按顺序排列的,如果这块内存还未使用必定是一块链的起始
9811015 {
982- node_free -> next -> linear_last = node_free -> linear_last ; // 使下一个节点指向连续内存块的最后一个节点
1016+ // 找到这块内存了
1017+ node_prev -> next = node_free -> next ; // 从空闲链表中移除
1018+ if (node_free -> linear_last != node_free ) // 非自旋节点,证明下一个节点跟这个节点是连续的(一定存在下一个节点)
1019+ {
1020+ node_free -> next -> linear_last = node_free -> linear_last ; // 使下一个节点指向连续内存块的最后一个节点
1021+ }
1022+ pool -> list_free .record_now -= need_count ;
1023+ pool -> record_min = MIN (pool -> record_min , pool -> list_free .record_now );
1024+ node -> block_count += need_count ;
1025+ ret_ptr = ptr ; // 赋值用于下面判断realloc是否完成,不能ATOMIC域内直接return
1026+ break ;
1027+ }
1028+ node_prev = node_free -> linear_last ;
1029+ node_free = node_free -> linear_last -> next ;
1030+ if ((size_t )node_free > (size_t )node ) // 遍历到需要内存后面了证明需要分配的内存不再空闲链表中
1031+ {
1032+ break ;
9831033 }
984-
985- ret_ptr = ptr ; // 赋值用于下面判断realloc是否完成,不能ATOMIC域内直接return
986- break ;
9871034 }
988-
989- node_prev = node_free -> linear_last ;
990- node_free = node_free -> linear_last -> next ;
991-
992- if ((size_t )node_free > (size_t )node ) // 遍历到需要内存后面了证明需要分配的内存不再空闲链表中
1035+ }
1036+ }
1037+ }
1038+ else if (need_count > 1 ) // 需要两个及以上连续内存块
1039+ {
1040+ node = (fc_pool_header_t * )((uint8_t * )node + node -> block_count * node_size ); // 直接定位到需要取出的内存块第一个节点位置
1041+ node_end = (fc_pool_header_t * )((uint8_t * )node + (need_count - 1 ) * node_size ); // 得到需要分配出去的最后一个节点位置
1042+ {
1043+ FC_ATOMIC_SCOPE
1044+ {
1045+ // 遍历空闲链表看需要取出的内存块是否还在空闲链表中
1046+ node_free = pool -> list_free .next ;
1047+ node_prev = & (pool -> list_free );
1048+ while (node_free ) // 最坏O(n)
9931049 {
994- break ;
1050+ if ((size_t )node_free == (size_t )node && (size_t )(node_free -> linear_last ) >= (size_t )node_end ) // 链式内存是按顺序排列的,如果这块内存还未使用必定是一块链的起始,从这块内存开始到node_end都是空闲的
1051+ {
1052+ // 找到这块内存了
1053+ node_prev -> next = node_end -> next ; // 从空闲链表中移除
1054+ if (node_free -> linear_last != node_end ) // 起始节点指向的最后一个连续节点不是分配出去的最后一个节点
1055+ {
1056+ node_end -> next -> linear_last = node_free -> linear_last ; // 使下一个节点指向连续内存块的最后一个节点
1057+ }
1058+ pool -> list_free .record_now -= need_count ;
1059+ pool -> record_min = MIN (pool -> record_min , pool -> list_free .record_now );
1060+ node -> block_count += need_count ;
1061+ ret_ptr = ptr ; // 赋值用于下面判断realloc是否完成,不能ATOMIC域内直接return
1062+ break ;
1063+ }
1064+ node_prev = node_free -> linear_last ;
1065+ node_free = node_free -> linear_last -> next ;
1066+ if ((size_t )node_free > (size_t )node ) // 遍历到需要内存后面了证明需要分配的内存不再空闲链表中
1067+ {
1068+ break ;
1069+ }
9951070 }
9961071 }
9971072 }
9981073 }
9991074 }
1000- else if ( need_count > 1 ) // 需要两个及以上连续内存块
1075+ else
10011076 {
1002- node = (fc_pool_header_t * )((uint8_t * )node + node -> block_count * node_size ); // 直接定位到需要取出的内存块第一个节点位置
1003- node_end = (fc_pool_header_t * )((uint8_t * )node + (need_count - 1 ) * node_size ); // 得到需要分配出去的最后一个节点位置
1004-
1077+ // need_count >= 1,需要判断连续的内存块是否被使用,内存块未排序
1078+ size_t count = 0 ;
1079+ fc_pool_header_t * node_part_front = & (pool -> list_free ); // 需要提取出的内存块的前一个节点
1080+ node_prev = (fc_pool_header_t * )((uint8_t * )node + node -> block_count * node_size ); // 直接定位到需要取出的内存块第一个节点位置
1081+ node_end = (fc_pool_header_t * )((uint8_t * )node + (need_count - 1 ) * node_size ); // 得到需要分配出去的最后一个节点位置
1082+ FC_ATOMIC_SCOPE
10051083 {
1006- FC_ATOMIC_SCOPE
1084+ node_free = pool -> list_free .next ;
1085+ while (node_free )
10071086 {
1008- // 遍历空闲链表看需要取出的内存块是否还在空闲链表中
1009- node_free = pool -> list_free .next ;
1010- node_prev = & (pool -> list_free );
1011- while (node_free ) // 最坏O(n)
1087+ if ((size_t )node_free >= (size_t )node_prev && (size_t )node_free <= (size_t )node_end )
10121088 {
1013- if ((size_t )node_free == (size_t )node && (size_t )(node_free -> linear_last ) >= (size_t )node_end ) // 链式内存是按顺序排列的,如果这块内存还未使用必定是一块链的起始,从这块内存开始到node_end都是空闲的
1089+ count ++ ;
1090+ if (count >= need_count )
10141091 {
1015- // 找到这块内存了
1016- node_prev -> next = node_end -> next ; // 从空闲链表中移除
1017-
1018- if (node_free -> linear_last != node_end ) // 起始节点指向的最后一个连续节点不是分配出去的最后一个节点
1092+ break ;
1093+ }
1094+ }
1095+ node_free = node_free -> next ;
1096+ }
1097+ if (count >= need_count )
1098+ {
1099+ node_free = pool -> list_free .next ; // 从头开始,一边遍历一边提取
1100+ // 从链中提取出需要的内存块
1101+ while (node_free )
1102+ {
1103+ if ((size_t )node_free >= (size_t )node_prev && (size_t )node_free <= (size_t )node_end )
1104+ {
1105+ node_part_front -> next = node_free -> next ; // 从链中移除
1106+ if ((size_t )(node_free -> linear_last ) != (size_t )node_free ) // 非自旋节点,证明下一个节点跟这个节点是连续的(一定存在下一个节点),无需判断(NULL != node->next)
10191107 {
1020- node_end -> next -> linear_last = node_free -> linear_last ; // 使下一个节点指向连续内存块的最后一个节点
1108+ node_free -> next -> linear_last = node_free -> linear_last ; // 使下一个节点指向连续内存块的最后一个节点
1109+ }
1110+ count -- ;
1111+ if (count <= 0 )
1112+ {
1113+ pool -> list_free .record_now -= need_count ;
1114+ pool -> record_min = MIN (pool -> record_min , pool -> list_free .record_now );
1115+ node -> block_count += need_count ;
1116+ ret_ptr = ptr ; // 赋值用于下面判断realloc是否完成,不能ATOMIC域内直接return
1117+ break ;
10211118 }
1022-
1023- ret_ptr = ptr ; // 赋值用于下面判断realloc是否完成,不能ATOMIC域内直接return
1024- break ;
10251119 }
1026-
1027- node_prev = node_free -> linear_last ;
1028- node_free = node_free -> linear_last -> next ;
1029-
1030- if ((size_t )node_free > (size_t )node ) // 遍历到需要内存后面了证明需要分配的内存不再空闲链表中
1120+ else
10311121 {
1032- break ;
1122+ node_part_front = node_free ;
10331123 }
1124+ node_free = node_free -> next ;
10341125 }
10351126 }
10361127 }
10371128 }
1038- else if (0 == need_count ) // 当前链上还有空闲内存仅仅修改标记大小
1039- {
1040- // 保持不变,仅仅修改标记大小
1041- fc_pool_mark_used (ptr , size ); // 标记实际使用大小
1042- return ptr ;
1043- }
1044- else if (need_count < 0 ) // 还要释放部分内存,正常使用比较少
1045- {
1046- node = (fc_pool_header_t * )((uint8_t * )node - (node -> block_count + need_count ) * node_size ); // 定位到需要释放的内存块第一个节点位置
1047- ret_ptr = fc_pool_skip_header (node );
1048- fc_pool_free (pool , ret_ptr );
1049- ret_ptr = ptr ; // 赋值用于下面判断realloc是否完成
1050- }
10511129 }
1052-
10531130 if (ret_ptr ) // 执行到这儿且不为空证明正常完成了realloc操作(基于原始内存)
10541131 {
10551132 fc_pool_mark_used (ret_ptr , size ); // 标记实际使用大小
10561133 }
1057- else
1058- {
1059- ret_ptr = fc_pool_malloc (pool , size ); // 重新分配内存
1060- if (ret_ptr ) // 分配成功
1061- {
1062- memcpy (ret_ptr , ptr , size ); // 复制内存
1063- fc_pool_free (pool , ptr ); // 释放旧内存
1064- }
1065- }
1066-
10671134 return ret_ptr ;
10681135}
10691136
@@ -1223,6 +1290,18 @@ void *fc_header_fifo_pop(fc_pool_header_t *header)
12231290 return (void * )(node ? (uint8_t * )node + sizeof (fc_pool_header_t ) : NULL );
12241291}
12251292
1293+ /**
1294+ * @brief 从fifo used链表头部查看一条链式非连续内存块,O(1)复杂度
1295+ *
1296+ * @param header
1297+ * @return void*
1298+ */
1299+ void * fc_header_fifo_peek (fc_pool_header_t * header )
1300+ {
1301+ fc_assert (header != NULL );
1302+ return (void * )(header -> next ? (uint8_t * )header -> next + sizeof (fc_pool_header_t ) : NULL );
1303+ }
1304+
12261305#if 0
12271306/**
12281307 * @brief 检查内存池是否正常
0 commit comments