代理模式

A是B的代理,对B的访问都可以通过对A的访问来实现。为什么要这样?因为对B的访问可能需要跨进程,可能需要复杂的逻辑判断,可能需要。。。总之比较麻烦,所以B为了提供给别人一个好用的接口,就创建了自己的代理A。

在大名鼎鼎的Binder通信里,就是用Bp来做Bn的代理,Bp可以放在访问者进程里,从而封装了麻烦的跨进程调用。



还有一个例子是AudioTrack和AudioFlinger在操作匿名共享内存的时候,使用了ClientProxy,ServerProxy。我们可以看到,它们提供的接口都是类似的,但是却封装了复杂的循环buffer前后指针判断逻辑和跨进程操作。



{
protected:
    ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
            bool isOut, bool clientInServer);
public:
    virtual ~ServerProxy() { }

    // Obtain a buffer with filled frames (writing) or empty frames (reading).
    // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
    // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
    // sets or extends the unreleased frame count.
    // Always non-blocking.
    // On entry:
    //  buffer->mFrameCount should be initialized to maximum number of desired frames,
    //      which must be > 0.
    //  buffer->mNonContig is unused.
    //  buffer->mRaw is unused.
    //  ackFlush is true iff being called from Track::start to acknowledge a pending flush.
    // On exit:
    //  buffer->mFrameCount has the actual number of contiguous available frames,
    //      which is always 0 when the return status != NO_ERROR.
    //  buffer->mNonContig is the number of additional non-contiguous available frames.
    //  buffer->mRaw is a pointer to the first available frame,
    //      or NULL when buffer->mFrameCount == 0.
    // The return status is one of:
    //  NO_ERROR    Success, buffer->mFrameCount > 0.
    //  WOULD_BLOCK No frames are available.
    //  NO_INIT     Shared memory is corrupt.
    virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush = false);

    // Release (some of) the frames last obtained.
    // On entry, buffer->mFrameCount should have the number of frames to release,
    // which must (cumulatively) be <= the number of frames last obtained but not yet released.
    // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
    // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
    // On exit:
    //  buffer->mFrameCount is zero.
    //  buffer->mRaw is NULL.
    virtual void        releaseBuffer(Buffer* buffer);

protected:
    size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
    int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
}
// Proxy seen by AudioTrack client and AudioRecord client
class ClientProxy : public Proxy {
public:
    ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
            bool isOut, bool clientInServer);
    virtual ~ClientProxy() { }

    static const struct timespec kForever;
    static const struct timespec kNonBlocking;

    // Obtain a buffer with filled frames (reading) or empty frames (writing).
    // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
    // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
    // sets or extends the unreleased frame count.
    // On entry:
    //  buffer->mFrameCount should be initialized to maximum number of desired frames,
    //      which must be > 0.
    //  buffer->mNonContig is unused.
    //  buffer->mRaw is unused.
    //  requested is the requested timeout in local monotonic delta time units:
    //      NULL or &kNonBlocking means non-blocking (zero timeout).
    //      &kForever means block forever (infinite timeout).
    //      Other values mean a specific timeout in local monotonic delta time units.
    //  elapsed is a pointer to a location that will hold the total local monotonic time that
    //      elapsed while blocked, or NULL if not needed.
    // On exit:
    //  buffer->mFrameCount has the actual number of contiguous available frames,
    //      which is always 0 when the return status != NO_ERROR.
    //  buffer->mNonContig is the number of additional non-contiguous available frames.
    //  buffer->mRaw is a pointer to the first available frame,
    //      or NULL when buffer->mFrameCount == 0.
    // The return status is one of:
    //  NO_ERROR    Success, buffer->mFrameCount > 0.
    //  WOULD_BLOCK Non-blocking mode and no frames are available.
    //  TIMED_OUT   Timeout occurred before any frames became available.
    //              This can happen even for infinite timeout, due to a spurious wakeup.
    //              In this case, the caller should investigate and then re-try as appropriate.
    //  DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create.
    //  -EINTR      Call has been interrupted.  Look around to see why, and then perhaps try again.
    //  NO_INIT     Shared memory is corrupt.
    // Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0.
    status_t    obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL,
            struct timespec *elapsed = NULL);

    // Release (some of) the frames last obtained.
    // On entry, buffer->mFrameCount should have the number of frames to release,
    // which must (cumulatively) be <= the number of frames last obtained but not yet released.
    // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
    // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
    // On exit:
    //  buffer->mFrameCount is zero.
    //  buffer->mRaw is NULL.
    void        releaseBuffer(Buffer* buffer);

    // Call after detecting server's death
    void        binderDied();

    // Call to force an obtainBuffer() to return quickly with -EINTR
    void        interrupt();

    size_t      getPosition() {
        return mEpoch + mCblk->mServer;
    }

    void        setEpoch(size_t epoch) {
        mEpoch = epoch;
    }

    void        setMinimum(size_t minimum) {
        // This can only happen on a 64-bit client
        if (minimum > UINT32_MAX) {
            minimum = UINT32_MAX;
        }
        mCblk->mMinimum = (uint32_t) minimum;
    }

    // Return the number of frames that would need to be obtained and released
    // in order for the client to be aligned at start of buffer
    virtual size_t  getMisalignment();

    size_t      getEpoch() const {
        return mEpoch;
    }

    size_t      getFramesFilled();

private:
    size_t      mEpoch;
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值