1 // Copyright 2014 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "android/base/synchronization/AndroidMessageChannel.h" 16 17 namespace android { 18 namespace base { 19 namespace guest { 20 MessageChannelBase(size_t capacity)21MessageChannelBase::MessageChannelBase(size_t capacity) : mCapacity(capacity) {} 22 size() const23size_t MessageChannelBase::size() const { 24 AutoLock lock(mLock); 25 return mCount; 26 } 27 stop()28void MessageChannelBase::stop() { 29 android::base::guest::AutoLock lock(mLock); 30 mStopped = true; 31 mCount = 0; 32 mCanRead.broadcast(); 33 mCanWrite.broadcastAndUnlock(&lock); 34 } 35 isStopped() const36bool MessageChannelBase::isStopped() const { 37 AutoLock lock(mLock); 38 return isStoppedLocked(); 39 } 40 waitForEmpty()41void MessageChannelBase::waitForEmpty() { 42 AutoLock lock(mLock); 43 while (mCount > 0) { 44 mCanWrite.wait(&lock); 45 } 46 } 47 beforeWrite()48size_t MessageChannelBase::beforeWrite() { 49 mLock.lock(); 50 while (mCount >= mCapacity && !mStopped) { 51 mCanWrite.wait(&mLock); 52 } 53 // Return value is undefined if stopped, so let's save a branch and skip the 54 // check for it. 55 size_t result = mPos + mCount; 56 if (result >= mCapacity) { 57 result -= mCapacity; 58 } 59 return result; 60 } 61 beforeTryWrite()62Optional<size_t> MessageChannelBase::beforeTryWrite() { 63 mLock.lock(); 64 65 if (mCount >= mCapacity || mStopped) { 66 return {}; 67 } 68 size_t result = mPos + mCount; 69 if (result >= mCapacity) { 70 result -= mCapacity; 71 } 72 return result; 73 } 74 afterWrite(bool success)75void MessageChannelBase::afterWrite(bool success) { 76 if (success) { 77 ++mCount; 78 } 79 mCanRead.signalAndUnlock(&mLock); 80 } 81 beforeRead()82size_t MessageChannelBase::beforeRead() { 83 mLock.lock(); 84 while (mCount == 0 && !mStopped) { 85 mCanRead.wait(&mLock); 86 } 87 return mPos; // return value is undefined if stopped, so let's save a branch 88 } 89 beforeTryRead()90Optional<size_t> MessageChannelBase::beforeTryRead() { 91 mLock.lock(); 92 93 if (mCount == 0 || mStopped) { 94 return {}; 95 } 96 return mPos; 97 } 98 beforeTimedRead(uint64_t wallTimeUs)99Optional<size_t> MessageChannelBase::beforeTimedRead(uint64_t wallTimeUs) { 100 mLock.lock(); 101 102 while (mCount == 0 && !mStopped) { 103 if (!mCanRead.timedWait(&mLock, wallTimeUs)) { 104 return {}; 105 } 106 } 107 return mPos; 108 } 109 afterRead(bool success)110void MessageChannelBase::afterRead(bool success) { 111 if (success) { 112 if (++mPos == mCapacity) { 113 mPos = 0U; 114 } 115 --mCount; 116 } 117 mCanWrite.signalAndUnlock(&mLock); 118 } 119 120 } // namespace guest 121 } // namespace base 122 } // namespace android 123