⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shared.c

📁 多线程库
💻 C
字号:
#include "shared.h"#include <string>extern "C" {#   include <sys/types.h>#   include <sys/stat.h>#   include <fcntl.h>#   include <errno.h>#   include "cloning.h"};shared_mem::shared_mem(){  _perm             = IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;  _key_root         = new char[80];  _blocks           = 0;  _work_area._file  = 0;  change_proj( "/tmp/project" );}shared_mem::shared_mem(const char *p_root){  _perm             = IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;  _key_root         = new char[80];  _blocks           = 0;  _work_area._file  = 0;  change_proj( p_root );}shared_mem::~shared_mem(){  cleanup();  delete _key_root;}void shared_mem::change_proj(const char *p_root){  strncpy( _key_root,p_root,79 );}void shared_mem::change_perm(int p_perm){  _perm = p_perm&0777;}int shared_mem::create_proj(const char *p_id){  int fd;  string s = _key_root;  sto_iterator i;  _key_lock.lock();#ifdef DEBUG  cout << "create_proj(" << p_id << ")\n";#endif  if ( p_id && strlen(p_id) > 0 ) {    s += "_";    s += p_id;  }  fd = open( s.c_str(),O_CREAT,_perm );  if ( fd != -1 ) {    close( fd );    for( i=_shared.begin();(i != _shared.end());i++ )      if ( (*i)._file != 0 && strcmp((*i)._file,s.c_str()) == 0 ) {	_key_lock.unlock();	return (*i)._id;      }    _work_area._id   = ++_blocks;    _work_area._key  = -1;    _work_area._file = strdup( s.c_str() );    _work_area._proj = 0;    _work_area._ptr  = 0;    _work_area._page = 0;    _work_area._mid  = 0;#ifdef DEBUG    cout << "new project " << _blocks << endl;#endif    _shared.push_back( _work_area );  } else    return -1;  _key_lock.unlock();  return _blocks;}key_t shared_mem::get_key(const char *p_id,int p_proj){  string s = _key_root;  key_t key = -1;  sto_iterator i;  _key_lock.lock();  if ( p_id && strlen(p_id) > 0 ) {    s += "_";    s += p_id;  }  for( i=_shared.begin();(i != _shared.end());i++ )    if ( strcmp((*i)._file,s.c_str()) == 0 && (*i)._proj == p_proj ) {      key = (*i)._key;      break;    }  _key_lock.unlock();  return key;}key_t shared_mem::make_key(int p_proj){  sto_iterator k = _shared.end();  sto_iterator i = _shared.begin();  _key_lock.lock();#ifdef DEBUG  cout << "make_key(" << p_proj << ")\n";#endif  _work_area._key = -1;  for( ;(i != _shared.end());i++ )    if ( (*i)._id == p_proj )      if ( k == _shared.end() || (*i)._key == -1 || (*k)._proj < (*i)._proj )	k = i;  if ( k != _shared.end() ) {    if ( (*k)._key != -1 ) {      _work_area = (*k);      if ( ++_work_area._proj != 0 ) {	_work_area._key  = ftok( _work_area._file,_work_area._proj );#ifdef DEBUG	cout << "new key " << _work_area._key << endl;#endif	_shared.push_back( _work_area );      }    } else {      _work_area._key = (*k)._key = ftok( (*k)._file,(*k)._proj );#ifdef DEBUG      cout << "added a key " << (*k)._key << endl;#endif    }  }  _key_lock.unlock();  return _work_area._key;}list<shared_mem::mem_entry>::iteratorshared_mem::getmem(sto_iterator i,size_t p_size){  size_t total_size = ((p_size/PAGE_SIZE)+1)*PAGE_SIZE;  _mem_entry._size = 0;  (*i)._mid = shmget( (*i)._key,p_size,IPC_CREAT|_perm );  if ( (*i)._mid == -1 )    return _free_list.end();  (*i)._ptr  = shmat( (*i)._mid,0,0 );  (*i)._page = total_size;#ifdef DEBUG  cout.form("Got a segment %p, sized %d\n",(*i)._ptr,(*i)._page);#endif  _mem_entry._size = total_size;  _mem_entry._data = (*i)._ptr;  return _free_list.insert( _free_list.end(),_mem_entry );}void shared_mem::fragment(mem_iterator i,size_t p_size){#ifdef DEBUG  cout.form("Fragmenting %p",(*i)._data);  cout << " cutting out " << p_size;#endif  _mem_entry._size = p_size;  _mem_entry._data = (*i)._data;  (*i)._size      -= p_size;  (*i)._data       = (void *)((long)(*i)._data + p_size);#ifdef DEBUG  cout << " redusing it to " << (*i)._size << endl;#endif}void *shared_mem::keyalloc(key_t p_key,size_t p_size){  void *ptr = 0;  sto_iterator i;  // Notice the order of the locks, doing it the other way around  // may cause a deadlock... see: alloc-fillup  _mem_lock.lock();  _key_lock.lock();  for( i=_shared.begin();(i != _shared.end());i++ )    if ( (*i)._key == p_key && (*i)._page <= p_size ) {      ptr = (*i)._ptr;      break;    }  if ( ptr == 0 && i != _shared.end() )    fragment( getmem(i,p_size),p_size );  _key_lock.unlock();  _mem_lock.unlock();  return ptr;}void *shared_mem::alloc(size_t p_size,int p_proj){  mem_iterator i,j;  _mem_lock.lock();#ifdef DEBUG  cout << "alloc(" << p_size << "," << p_proj << ")\n";#endif  j = _free_list.end();  for ( i=_free_list.begin();(i != _free_list.end());i++ )    if ( (*i)._size >= p_size )      if ( j == _free_list.end() || (*i)._size < (*j)._size )	j = i;  if ( j == _free_list.end() ) {    j = fillup(p_size,p_proj);    if ( j == _free_list.end() ) {      _mem_lock.unlock();      return 0;   // if we throw an error, we need to cleanup first.    }  }  fragment( j,p_size );  if ( (*j)._size == 0 )    _free_list.erase( j );  _used_list.push_back(_mem_entry);  _mem_lock.unlock();  return _mem_entry._data;}list<shared_mem::mem_entry>::iteratorshared_mem::fillup(size_t p_size, int p_proj){  key_t key = -1;  sto_iterator i;#ifdef DEBUG  cout << "fillup(" << p_size << "," << p_proj << ")\n";#endif  if ( p_proj == 0 )    p_proj = create_proj( 0 );  for( i=_shared.begin();(i != _shared.end());i++ )    if ( (*i)._proj == p_proj )      if ( (*i)._ptr == 0  && (*i)._key != -1 ) {	key = (*i)._key;	break;      }  if ( key == -1 )    key = make_key( p_proj );  if ( key != -1 ) {    for( i=_shared.begin();(i != _shared.end());i++ )      if ( (*i)._key == key )	break;    return getmem( i,p_size );  }  return _free_list.end();}void shared_mem::dealloc(void *p_ptr){  struct shmid_ds sm;  mem_iterator i;  sto_iterator k;  _mem_lock.lock();  for( i=_used_list.begin();(i != _used_list.end());i++ )    if ( p_ptr == (*i)._data )      break;  if ( i == _used_list.end() )    return;   // memory doesn't belong to us, or fragmented.  _mem_entry = (*i);  _used_list.erase( i );#ifdef DEBUG  cout.form("Returning %p(%d) ",_mem_entry._data,_mem_entry._size);#endif  // Now collect all consequtive freed memory  for ( i=_free_list.begin();(i != _free_list.end());i++ ) {#ifdef DEBUG    cout.form(" ?%p(%d)",(*i)._data,(*i)._size);#endif    if ( (*i)._data == (void *)((long)_mem_entry._data - (*i)._size) ) {      _mem_entry._size += (*i)._size;      _mem_entry._data  = (*i)._data;#ifdef DEBUG      cout << " concatenated";#endif      i = _free_list.erase( i );    }    if ( _mem_entry._data == (void *)((long)(*i)._data - _mem_entry._size) ) {      _mem_entry._size += (*i)._size;#ifdef DEBUG      cout << " attached";#endif      i = _free_list.erase( i );    }#ifdef DEBUG    cout << endl;#endif  }  // Now we have a pointer to free memory, now let's see if we  // should return this memory to the system.  _key_lock.lock();  for( k=_shared.begin();(k != _shared.end());k++ )     if ( (*k)._ptr == _mem_entry._data && (*k)._page == _mem_entry._size ) {      // Ah ha... we've freed the whole page.#ifdef DEBUG      cout.form("Freeing dereferenced page %p(%d)\n",(*k)._ptr,(*k)._page);#endif      shmctl( (*k)._mid,IPC_RMID,&sm );      shmdt( (*k)._ptr );      (*k)._ptr  = 0;      (*k)._mid  = 0;      (*k)._page = 0;      break;    }  if ( k == _shared.end() )    _free_list.push_back(_mem_entry);  _key_lock.unlock();  _mem_lock.unlock();}//// cleanup//// Cleanup all memory allocated pages, by removing them// and marking them for destruction.//// dilemma://  Suppose there are some dirty pages around, a user hasn't//  freed all memory, that he isn't using... what should I do?//  should I destroy the page, or leave it?  At this poiint,//  I am destroying all references to shared memory.void shared_mem::cleanup(){  struct shmid_ds sm;  sto_iterator i;  _key_lock.lock();  _mem_lock.lock();  for( i=_shared.begin();(i != _shared.end());i++ ) {    if ( (*i)._ptr != 0 ) {#ifdef DEBUG      cout.form("Mark page %p for removal\n",(*i)._ptr);#endif      // The page will be removed, when unattached... the      // unattachement will occurr normally on exit.      shmctl( (*i)._mid,IPC_RMID,&sm );    }  }  // We have destroyed the pages, no re-entry is allowed.}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -