182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten/*
282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *
482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * you may not use this file except in compliance with the License.
682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * You may obtain a copy of the License at
782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *
882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
982b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *
1082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * Unless required by applicable law or agreed to in writing, software
1182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * See the License for the specific language governing permissions and
1482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * limitations under the License.
1582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten */
1682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
1782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten#include "sles_allinclusive.h"
1882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
19158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
204f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Exclusively lock an object */
21158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
223190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#ifdef USE_DEBUG
233190a0da044e122c1c617e30d1d364701fb27110Glenn Kastenvoid object_lock_exclusive_(IObject *this, const char *file, int line)
243190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten{
253190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    int ok;
263190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    ok = pthread_mutex_trylock(&this->mMutex);
273190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    if (0 != ok) {
2807c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        // pthread_mutex_timedlock_np is not available, but wait up to 100 ms
2907c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        static const useconds_t backoffs[] = {1, 10000, 20000, 30000, 40000};
3007c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        unsigned i = 0;
3107c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        for (;;) {
3207c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten            usleep(backoffs[i]);
3307c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten            ok = pthread_mutex_trylock(&this->mMutex);
3407c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten            if (0 == ok)
3507c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                break;
3607c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten            if (++i >= (sizeof(backoffs) / sizeof(backoffs[0]))) {
37227b8b5fe36d5385bbb23d63198bc8e72bfda5d3Glenn Kasten                SL_LOGW("%s:%d: object %p was locked by %p at %s:%d\n",
3807c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                    file, line, this, *(void **)&this->mOwner, this->mFile, this->mLine);
3907c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                // attempt one more time; maybe this time we will be successful
4007c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                ok = pthread_mutex_lock(&this->mMutex);
4107c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                assert(0 == ok);
4207c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                break;
4307c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten            }
4407c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        }
453190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    }
463190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    pthread_t zero;
473190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    memset(&zero, 0, sizeof(pthread_t));
4807c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    if (0 != memcmp(&zero, &this->mOwner, sizeof(pthread_t))) {
4907c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        if (pthread_equal(pthread_self(), this->mOwner)) {
5007c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten            SL_LOGE("%s:%d: object %p was recursively locked by %p at %s:%d\n",
5107c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                file, line, this, *(void **)&this->mOwner, this->mFile, this->mLine);
5207c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        } else {
5307c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten            SL_LOGE("%s:%d: object %p was left unlocked in unexpected state by %p at %s:%d\n",
5407c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten                file, line, this, *(void **)&this->mOwner, this->mFile, this->mLine);
5507c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        }
5607c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten        assert(false);
5707c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    }
583190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    this->mOwner = pthread_self();
593190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    this->mFile = file;
603190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    this->mLine = line;
613190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten}
623190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#else
6307c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kastenvoid object_lock_exclusive(IObject *this)
6482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
6582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    int ok;
6682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    ok = pthread_mutex_lock(&this->mMutex);
6782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    assert(0 == ok);
6882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
693190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#endif
7082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
71158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
724f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Exclusively unlock an object and do not report any updates */
73158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
743190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#ifdef USE_DEBUG
75974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kastenvoid object_unlock_exclusive_(IObject *this, const char *file, int line)
76974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten{
773190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    assert(pthread_equal(pthread_self(), this->mOwner));
783190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    assert(NULL != this->mFile);
793190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    assert(0 != this->mLine);
803190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    memset(&this->mOwner, 0, sizeof(pthread_t));
81974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    this->mFile = file;
82974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    this->mLine = line;
8382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    int ok;
8482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    ok = pthread_mutex_unlock(&this->mMutex);
8582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    assert(0 == ok);
8682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
87974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten#else
88974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kastenvoid object_unlock_exclusive(IObject *this)
89974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten{
90974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    int ok;
91974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    ok = pthread_mutex_unlock(&this->mMutex);
92974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    assert(0 == ok);
93974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten}
94974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten#endif
9582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
96158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
974f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Exclusively unlock an object and report updates to the specified bit-mask of
984f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten *  attributes
994f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten */
100158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
101974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten#ifdef USE_DEBUG
102974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kastenvoid object_unlock_exclusive_attributes_(IObject *this, unsigned attributes,
103974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    const char *file, int line)
104974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten#else
10515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kastenvoid object_unlock_exclusive_attributes(IObject *this, unsigned attributes)
106974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten#endif
10715f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten{
1083190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten
1093190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#ifdef USE_DEBUG
1103190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    assert(pthread_equal(pthread_self(), this->mOwner));
1113190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    assert(NULL != this->mFile);
1123190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    assert(0 != this->mLine);
1133190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#endif
1143190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten
11515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    int ok;
11615f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    SLuint32 objectID = IObjectToObjectID(this);
11715f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    CAudioPlayer *ap;
11823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
11923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // FIXME The endless if statements are getting ugly, should use bit search
12023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
12115f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    // Android likes to see certain updates synchronously
122d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi
12315f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    if (attributes & ATTR_GAIN) {
12415f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        switch (objectID) {
12515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        case SL_OBJECTID_AUDIOPLAYER:
12615f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            attributes &= ~ATTR_GAIN;   // no need to process asynchronously also
12715f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            ap = (CAudioPlayer *) this;
12815f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten#ifdef ANDROID
129f66a508b11e327670a6bf5a8cf9c106f215e3b39Jean-Michel Trivi            android_audioPlayer_volumeUpdate(ap);
13015f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten#else
13115f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            audioPlayerGainUpdate(ap);
13215f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten#endif
13315f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            break;
13415f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        case SL_OBJECTID_OUTPUTMIX:
13515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            // FIXME update gains on all players attached to this outputmix
13603716fc64636a68ba59881508e80550b948f0f40Glenn Kasten            SL_LOGD("[ FIXME: gain update on an SL_OBJECTID_OUTPUTMIX to be implemented ]");
137d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi            break;
138d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi        case SL_OBJECTID_MIDIPLAYER:
139f51f5c6ec99ebc8f2c833a68f232bc1c874a7f2fGlenn Kasten            // MIDI
14003716fc64636a68ba59881508e80550b948f0f40Glenn Kasten            SL_LOGD("[ FIXME: gain update on an SL_OBJECTID_MIDIPLAYER to be implemented ]");
14115f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            break;
14215f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        default:
14315f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            break;
14415f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        }
14515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    }
146d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi
147d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi    if (attributes & ATTR_POSITION) {
148d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi        switch (objectID) {
149d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi        case SL_OBJECTID_AUDIOPLAYER:
150d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi#ifdef ANDROID
151bf53474b725519ebeab2997e975375d896ff91beGlenn Kasten            ap = (CAudioPlayer *) this;
15223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            attributes &= ~ATTR_POSITION;   // no need to process asynchronously also
153f66a508b11e327670a6bf5a8cf9c106f215e3b39Jean-Michel Trivi            android_audioPlayer_seek(ap, ap->mSeek.mPos);
154d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi#else
15523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            //audioPlayerTransportUpdate(ap);
156d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi#endif
157d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi            break;
158d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi        case SL_OBJECTID_MIDIPLAYER:
159f51f5c6ec99ebc8f2c833a68f232bc1c874a7f2fGlenn Kasten            // MIDI
16003716fc64636a68ba59881508e80550b948f0f40Glenn Kasten            SL_LOGD("[ FIXME: position update on an SL_OBJECTID_MIDIPLAYER to be implemented ]");
161d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi            break;
162d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi        default:
163d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi            break;
164d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi        }
165d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi    }
166d0222eec2f5ae565ab930fc1364950ab4530e1e8Jean-Michel Trivi
16715f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    if (attributes & ATTR_TRANSPORT) {
16815f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        if (SL_OBJECTID_AUDIOPLAYER == objectID) {
16923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#ifdef ANDROID
17015f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            attributes &= ~ATTR_TRANSPORT;   // no need to process asynchronously also
17115f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            ap = (CAudioPlayer *) this;
17215f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            // FIXME should only call when state changes
1738c5a381a265210f069a370565f10ce31bf886346Jean-Michel Trivi            android_audioPlayer_setPlayState(ap, false /*lockAP*/);
17415f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            // FIXME ditto, but for either eventflags or marker position
175f66a508b11e327670a6bf5a8cf9c106f215e3b39Jean-Michel Trivi            android_audioPlayer_useEventMask(ap);
17615f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten#else
17723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            //audioPlayerTransportUpdate(ap);
17815f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten#endif
17991ebb75cfa76cc573ced127e59cad7dd950ce08aJean-Michel Trivi        } else if (SL_OBJECTID_AUDIORECORDER == objectID) {
18091ebb75cfa76cc573ced127e59cad7dd950ce08aJean-Michel Trivi#ifdef ANDROID
18191ebb75cfa76cc573ced127e59cad7dd950ce08aJean-Michel Trivi            attributes &= ~ATTR_TRANSPORT;   // no need to process asynchronously also
18291ebb75cfa76cc573ced127e59cad7dd950ce08aJean-Michel Trivi            CAudioRecorder* ar = (CAudioRecorder *) this;
18391ebb75cfa76cc573ced127e59cad7dd950ce08aJean-Michel Trivi            android_audioRecorder_useEventMask(ar);
18491ebb75cfa76cc573ced127e59cad7dd950ce08aJean-Michel Trivi#endif
18515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        }
18615f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    }
18723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
18823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // ( buffer queue count is non-empty and play state == PLAYING ) became true
18923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    if (attributes & ATTR_ENQUEUE) {
19023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        if (SL_OBJECTID_AUDIOPLAYER == objectID) {
19123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            attributes &= ~ATTR_ENQUEUE;
19223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            ap = (CAudioPlayer *) this;
19323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            if (SL_PLAYSTATE_PLAYING == ap->mPlay.mState) {
194b746b8006289cf3baed344fc8d827c423963f553Jean-Michel Trivi#ifdef ANDROID
195614d5407d3fac1dae8975722f25e671642041282Jean-Michel Trivi                android_audioPlayer_bufferQueue_onRefilled(ap);
196b746b8006289cf3baed344fc8d827c423963f553Jean-Michel Trivi#endif
19723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            }
19823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        }
19923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
20023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
20115f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    if (attributes) {
20215f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        unsigned oldAttributesMask = this->mAttributesMask;
20315f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        this->mAttributesMask = oldAttributesMask | attributes;
20415f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        if (oldAttributesMask)
20515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten            attributes = ATTR_NONE;
20615f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    }
2073190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#ifdef USE_DEBUG
2083190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten    memset(&this->mOwner, 0, sizeof(pthread_t));
209974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    this->mFile = file;
210974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    this->mLine = line;
2113190a0da044e122c1c617e30d1d364701fb27110Glenn Kasten#endif
21215f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    ok = pthread_mutex_unlock(&this->mMutex);
21315f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    assert(0 == ok);
21431df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten    // first update to this interface since previous sync
21531df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten    if (attributes) {
21631df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten        unsigned id = this->mInstanceID;
21731df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten        if (0 != id) {
21831df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten            --id;
21931df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten            assert(MAX_INSTANCE > id);
22031df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten            IEngine *thisEngine = this->mEngine;
22131df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten            interface_lock_exclusive(thisEngine);
22231df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten            thisEngine->mChangedMask |= 1 << id;
22331df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten            interface_unlock_exclusive(thisEngine);
22431df22b193ea7c7c331d26a27fa6756a89c8ec3cGlenn Kasten        }
22515f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten    }
22615f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten}
22715f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten
228158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
2294f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Wait on the condition variable associated with the object; see pthread_cond_wait */
230158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
23107c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten#ifdef USE_DEBUG
23207c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kastenvoid object_cond_wait_(IObject *this, const char *file, int line)
23307c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten{
23407c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    // note that this will unlock the mutex, so we have to clear the owner
23507c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    assert(pthread_equal(pthread_self(), this->mOwner));
23607c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    assert(NULL != this->mFile);
23707c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    assert(0 != this->mLine);
23807c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    memset(&this->mOwner, 0, sizeof(pthread_t));
239974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    this->mFile = file;
240974aacf14bfe6869b7d0cda3abcaef46af335487Glenn Kasten    this->mLine = line;
24107c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    // alas we don't know the new owner's identity
24207c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    int ok;
24307c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    ok = pthread_cond_wait(&this->mCond, &this->mMutex);
24407c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    assert(0 == ok);
24507c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    // restore my ownership
24607c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    this->mOwner = pthread_self();
24707c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    this->mFile = file;
24807c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten    this->mLine = line;
24907c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten}
25007c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten#else
25182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenvoid object_cond_wait(IObject *this)
25282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
25382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    int ok;
25482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    ok = pthread_cond_wait(&this->mCond, &this->mMutex);
25582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    assert(0 == ok);
25682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
25707c35e6e57ff8945c4dd836be4486a62316ac64bGlenn Kasten#endif
25882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
259158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
2604f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Signal the condition variable associated with the object; see pthread_cond_signal */
261158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
26282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenvoid object_cond_signal(IObject *this)
26382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
26482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    int ok;
26582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    ok = pthread_cond_signal(&this->mCond);
26682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    assert(0 == ok);
26782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
268c37c934e00a96afe18aaadd9f9a1863c721bf8eaGlenn Kasten
269158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
2704f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten/** \brief Broadcast the condition variable associated with the object;
2714f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten *  see pthread_cond_broadcast
2724f924ff768d761f53db6fa2dbfb794ba7a65e776Glenn Kasten */
273158dbd1a71a890d29490198c8e5019081ac94ac3Glenn Kasten
274c37c934e00a96afe18aaadd9f9a1863c721bf8eaGlenn Kastenvoid object_cond_broadcast(IObject *this)
275c37c934e00a96afe18aaadd9f9a1863c721bf8eaGlenn Kasten{
276c37c934e00a96afe18aaadd9f9a1863c721bf8eaGlenn Kasten    int ok;
277c37c934e00a96afe18aaadd9f9a1863c721bf8eaGlenn Kasten    ok = pthread_cond_broadcast(&this->mCond);
278c37c934e00a96afe18aaadd9f9a1863c721bf8eaGlenn Kasten    assert(0 == ok);
279c37c934e00a96afe18aaadd9f9a1863c721bf8eaGlenn Kasten}
280