📄 sfpool.c
字号:
/* Copyright (c) Colorado School of Mines, 2006.*//* All rights reserved. */#include "sfhdr.h"/* Management of pools of streams.** If pf is not nil, f is pooled with pf and f becomes current;** otherwise, f is isolated from its pool. flag can be one of** 0 or SF_SHARE.**** Written by Kiem-Phong Vo.*//* Note that we do not free the space for a pool once it is allocated.** This is to prevent memory faults in calls such as sfsync(NULL) that walk the pool** link list and during such walks may free up streams&pools. Free pools will be** reused in newpool().*/#if __STD_Cstatic int delpool(reg Sfpool_t* p)#elsestatic int delpool(p)reg Sfpool_t* p;#endif{ POOLMTXSTART(p); if(p->s_sf && p->sf != p->array) free((Void_t*)p->sf); p->mode = SF_AVAIL; POOLMTXRETURN(p,0);}#if __STD_Cstatic Sfpool_t* newpool(reg int mode)#elsestatic Sfpool_t* newpool(mode)reg int mode;#endif{ reg Sfpool_t *p, *last = &_Sfpool; /* look to see if there is a free pool */ for(last = &_Sfpool, p = last->next; p; last = p, p = p->next) { if(p->mode == SF_AVAIL ) { p->mode = 0; break; } } if(!p) { POOLMTXLOCK(last); if(!(p = (Sfpool_t*) malloc(sizeof(Sfpool_t))) ) { POOLMTXUNLOCK(last); return NIL(Sfpool_t*); } (void)vtmtxopen(&p->mutex, VT_INIT); /* initialize mutex */ p->mode = 0; p->n_sf = 0; p->next = NIL(Sfpool_t*); last->next = p; POOLMTXUNLOCK(last); } POOLMTXSTART(p); p->mode = mode&SF_SHARE; p->s_sf = sizeof(p->array)/sizeof(p->array[0]); p->sf = p->array; POOLMTXRETURN(p,p);}/* move a stream to head */#if __STD_Cstatic int _sfphead(Sfpool_t* p, Sfio_t* f, int n)#elsestatic int _sfphead(p, f, n)Sfpool_t* p; /* the pool */Sfio_t* f; /* the stream */int n; /* current position in pool */#endif{ reg Sfio_t* head; reg ssize_t k, w, v; reg int rv; POOLMTXSTART(p); if(n == 0) POOLMTXRETURN(p,0); head = p->sf[0]; if(SFFROZEN(head) ) POOLMTXRETURN(p,-1); SFLOCK(head,0); rv = -1; if(!(p->mode&SF_SHARE) ) { if(SFSYNC(head) < 0) goto done; } else /* shared pool, data can be moved among streams */ { if(SFMODE(head,1) != SF_WRITE && _sfmode(head,SF_WRITE,1) < 0) goto done; /**/ASSERT((f->mode&(SF_WRITE|SF_POOL)) == (SF_WRITE|SF_POOL) ); /**/ASSERT(f->next == f->data); v = head->next - head->data; /* pending data */ if((k = v - (f->endb-f->data)) <= 0) k = 0; else /* try to write out amount exceeding f's capacity */ { if((w = SFWR(head,head->data,k,head->disc)) == k) v -= k; else /* write failed, recover buffer then quit */ { if(w > 0) { v -= w; memcpy(head->data,(head->data+w),v); } head->next = head->data+v; goto done; } } /* move data from head to f */ if((head->data+k) != f->data ) memcpy(f->data,(head->data+k),v); f->next = f->data+v; } f->mode &= ~SF_POOL; head->mode |= SF_POOL; head->next = head->endr = head->endw = head->data; p->sf[n] = head; p->sf[0] = f; rv = 0;done: head->mode &= ~SF_LOCK; /* partially unlock because it's no longer head */ POOLMTXRETURN(p,rv);}/* delete a stream from its pool */#if __STD_Cstatic int _sfpdelete(Sfpool_t* p, Sfio_t* f, int n)#elsestatic int _sfpdelete(p, f, n)Sfpool_t* p; /* the pool */Sfio_t* f; /* the stream */int n; /* position in pool */#endif{ POOLMTXSTART(p); p->n_sf -= 1; for(; n < p->n_sf; ++n) p->sf[n] = p->sf[n+1]; f->pool = NIL(Sfpool_t*); f->mode &= ~SF_POOL; if(p->n_sf == 0 || p == &_Sfpool) { if(p != &_Sfpool) delpool(p); goto done; } /* !_Sfpool, make sure head stream is an open stream */ for(n = 0; n < p->n_sf; ++n) if(!SFFROZEN(p->sf[n])) break; if(n < p->n_sf && n > 0) { f = p->sf[n]; p->sf[n] = p->sf[0]; p->sf[0] = f; } /* head stream has SF_POOL off */ f = p->sf[0]; f->mode &= ~SF_POOL; if(!SFFROZEN(f)) _SFOPEN(f); /* if only one stream left, delete pool */ if(p->n_sf == 1 ) { _sfpdelete(p,f,0); _sfsetpool(f); }done: POOLMTXRETURN(p,0);}#if __STD_Cstatic int _sfpmove(reg Sfio_t* f, reg int type)#elsestatic int _sfpmove(f,type)reg Sfio_t* f;reg int type; /* <0 : deleting, 0: move-to-front, >0: inserting */#endif{ reg Sfpool_t* p; reg int n; if(type > 0) return _sfsetpool(f); else { if(!(p = f->pool) ) return -1; for(n = p->n_sf-1; n >= 0; --n) if(p->sf[n] == f) break; if(n < 0) return -1; return type == 0 ? _sfphead(p,f,n) : _sfpdelete(p,f,n); }}#if __STD_CSfio_t* sfpool(reg Sfio_t* f, reg Sfio_t* pf, reg int mode)#elseSfio_t* sfpool(f,pf,mode)reg Sfio_t* f;reg Sfio_t* pf;reg int mode;#endif{ reg Sfpool_t* p; reg Sfio_t* rv; _Sfpmove = _sfpmove; if(!f) /* return head of pool of pf regardless of lock states */ { if(!pf) return NIL(Sfio_t*); else if(!pf->pool || pf->pool == &_Sfpool) return pf; else return pf->pool->sf[0]; } if(f) /* check for permissions */ { SFMTXLOCK(f); if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) { SFMTXUNLOCK(f); return NIL(Sfio_t*); } if(f->disc == _Sfudisc) (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); } if(pf) { SFMTXLOCK(pf); if((pf->mode&SF_RDWR) != pf->mode && _sfmode(pf,0,0) < 0) { if(f) SFMTXUNLOCK(f); SFMTXUNLOCK(pf); return NIL(Sfio_t*); } if(pf->disc == _Sfudisc) (void)sfclose((*_Sfstack)(pf,NIL(Sfio_t*))); } /* f already in the same pool with pf */ if(f == pf || (pf && f->pool == pf->pool && f->pool != &_Sfpool) ) { if(f) SFMTXUNLOCK(f); if(pf) SFMTXUNLOCK(pf); return pf; } /* lock streams before internal manipulations */ rv = NIL(Sfio_t*); SFLOCK(f,0); if(pf) SFLOCK(pf,0); if(!pf) /* deleting f from its current pool */ { if(!(p = f->pool) || p == &_Sfpool || _sfpmove(f,-1) < 0 || _sfsetpool(f) < 0) goto done; if((p = f->pool) == &_Sfpool || p->n_sf <= 0) rv = f; else rv = p->sf[0]; /* return head of pool */ goto done; } if(pf->pool && pf->pool != &_Sfpool) /* always use current mode */ mode = pf->pool->mode; if(mode&SF_SHARE) /* can only have write streams */ { if(SFMODE(f,1) != SF_WRITE && _sfmode(f,SF_WRITE,1) < 0) goto done; if(SFMODE(pf,1) != SF_WRITE && _sfmode(pf,SF_WRITE,1) < 0) goto done; if(f->next > f->data && SFSYNC(f) < 0) /* start f clean */ goto done; } if(_sfpmove(f,-1) < 0) /* isolate f from current pool */ goto done; if(!(p = pf->pool) || p == &_Sfpool) /* making a new pool */ { if(!(p = newpool(mode)) ) goto done; if(_sfpmove(pf,-1) < 0) /* isolate pf from its current pool */ goto done; pf->pool = p; p->sf[0] = pf; p->n_sf += 1; } f->pool = p; /* add f to pf's pool */ if(_sfsetpool(f) < 0) goto done; /**/ASSERT(p->sf[0] == pf && p->sf[p->n_sf-1] == f); SFOPEN(pf,0); SFOPEN(f,0); if(_sfpmove(f,0) < 0) /* make f head of pool */ goto done; rv = pf;done: if(f) { SFOPEN(f,0); SFMTXUNLOCK(f); } if(pf) { SFOPEN(pf,0); SFMTXUNLOCK(pf); } return rv;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -