ACE_Message_Block中的locking_strategy的使用

    接着上一次的写。
    先我们看看Ace_Message_Block中的locking_strategy锁到底作用在什么地方。
    通过查看ACE的源代码,我们可以发现,在Ace_Message_Block中根本没有保存这把锁,而是直接传入内部的ACE_Data_Block中。在ACE_Data_Block中,保存了这把锁。ACE_Data_Block使用这把锁来控制duplicate和release时的同步。
    可以这么说,如果你的程序中没有使用duplicate,那么,你在构造Ace_Message_Block的时候完全可以不用传递这个值,但如果你使用了duplicate,那么请一定加上这把锁。
    由上面分析,我们可以认为,一个ACE_Data_Block对应着一把锁。实际上也应该这样理解,但是,ACE的作者却不是这么用的。
    请看Ace_Message_Block的release和release_i()函数:
None.gif ACE_Message_Block  *  ACE_Message_Block::release ( void )
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  ACE_TRACE (
"ACE_Message_Block::release");
InBlock.gif
InBlock.gif  
// We want to hold the data block in a temporary variable because we
InBlock.gif  
// invoked "delete this;" at some point, so using this->data_block_
InBlock.gif  
// could be a bad idea.
InBlock.gif
  ACE_Data_Block *tmp = this->data_block ();
InBlock.gif
InBlock.gif  
// This flag is set to 1 when we have to destroy the data_block
InBlock.gif
  int destroy_dblock = 0;
InBlock.gif
InBlock.gif  ACE_Lock 
*lock = 0;
InBlock.gif
InBlock.gif  
// Do we have a valid data block
InBlock.gif
  if (this->data_block ())
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
// Grab the lock that belongs to my data block
InBlock.gif
      lock = this->data_block ()->locking_strategy ();
InBlock.gif
InBlock.gif      
// if we have a lock
InBlock.gif
      if (lock != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif          
// One guard for all
InBlock.gif
          ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock0);
InBlock.gif
InBlock.gif          
// Call non-guarded release with <lock>
InBlock.gif
          destroy_dblock = this->release_i (lock);
ExpandedSubBlockEnd.gif        }

InBlock.gif      
// This is the case when we have a valid data block but no lock
InBlock.gif
      else
InBlock.gif        
// Call non-guarded release with no lock
InBlock.gif
        destroy_dblock = this->release_i (0);
ExpandedSubBlockEnd.gif    }

InBlock.gif  
else
InBlock.gif    
// This is the case when we don't even have a valid data block
InBlock.gif
    destroy_dblock = this->release_i (0);
InBlock.gif
InBlock.gif  
if (destroy_dblock != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      ACE_Allocator 
*allocator = tmp->data_block_allocator ();
InBlock.gif      ACE_DES_FREE (tmp,
InBlock.gif                    allocator
->free,
InBlock.gif                    ACE_Data_Block);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif  
return 0;
ExpandedBlockEnd.gif}

None.gif
None.gif
int  ACE_Message_Block::release_i (ACE_Lock  * lock )
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  ACE_TRACE (
"ACE_Message_Block::release_i");
InBlock.gif
InBlock.gif  
// Free up all the continuation messages.
InBlock.gif
  if (this->cont_)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      ACE_Message_Block 
*mb = this->cont_;
InBlock.gif      ACE_Message_Block 
*tmp = 0;
InBlock.gif
InBlock.gif      
do
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif          tmp 
= mb;
InBlock.gif          mb 
= mb->cont_;
InBlock.gif          tmp
->cont_ = 0;
InBlock.gif
InBlock.gif          ACE_Data_Block 
*db = tmp->data_block ();
InBlock.gif          
if (tmp->release_i (lock!= 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif              ACE_Allocator 
*allocator = db->data_block_allocator ();
InBlock.gif              ACE_DES_FREE (db,
InBlock.gif                            allocator
->free,
InBlock.gif                            ACE_Data_Block);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif      
while (mb);
InBlock.gif
InBlock.gif      
this->cont_ = 0;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif  
int result = 0;
InBlock.gif
InBlock.gif  
if (ACE_BIT_DISABLED (this->flags_,
InBlock.gif                        ACE_Message_Block::DONT_DELETE) 
&&
InBlock.gif      
this->data_block ())
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
if (this->data_block ()->release_no_delete (lock== 0)
InBlock.gif        result 
= 1;
InBlock.gif      
this->data_block_ = 0;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif  
// We will now commit suicide: this object *must* have come from the
InBlock.gif  
// allocator given.
InBlock.gif
  if (this->message_block_allocator_ == 0)
InBlock.gif    delete 
this;
InBlock.gif  
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      ACE_Allocator 
*allocator = this->message_block_allocator_;
InBlock.gif      ACE_DES_FREE (
this,
InBlock.gif                    allocator
->free,
InBlock.gif                    ACE_Message_Block);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif  
return result;
ExpandedBlockEnd.gif}

看出什么问题来了不?
如果你有两个或者两个以上的Message_Block用cont()连接起来。在调用release时,ACE会用第一的Message_Block的锁去释放后面的Message_Block。这样,如果这几个Message_Block不时用的同一把锁的话,在Release的时候就会出错。
分析了上面的问题,现在我们讨论一下Message-Block的优化。
首先.ACE_Data_Block中的锁的优化。
        很多人使用的时候都是传入的一把锁给所有的ACE_Data_Block,结果每一个ACE_Message_Block,在duplicate 或者release的时候都需要获取这把锁。优化的方案就是为ACE_Data_Block都传一把锁进去,当然,在Release的时候就必须注意,不要直接调用ACE_Message_Block的Release函数。
其次ACE_Allocator的优化。
        ACE_Allocator中有一把锁用于维持链表的线程安全。当你整个应用程序就只有一个ACE_Allocator时,每一个池中的对象在分配或者释放的时候都需要获取这把锁,那么线程之间的碰撞时很激烈的,解决的办法也很简单。在程序中每一个ACE_Allocator不要太大,相当于再做一个ACE_Allocator的池。

转载于:https://www.cnblogs.com/tionase/archive/2006/08/29/486937.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值