blob: 84410a6db424805334940fd350864bfa703d7180 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
#include "ExSMReadyList.h"
#include "ExSMTask.h"
#include "ExSMTrace.h"
// NOTE: The SM ready list is accessed by both threads (main and
// reader) but does not have its own lock. By convention,
// modifications to the ready list are always performed while holding
// a lock on the SM task list (a global collection of all SM tasks in
// this process).
ExSMReadyList::ExSMReadyList()
: head_(NULL)
{
}
ExSMReadyList::~ExSMReadyList()
{
}
void ExSMReadyList::add(ExSMTask *t)
{
EXSM_TRACE(EXSM_TRACE_THR_ALL, "READY LIST ADD %p", t);
if (!head_)
{
// The list is currently empty. Set the head, next, and prev
// pointers to all point to the new task.
t->readyListNext_ = t;
t->readyListPrev_ = t;
head_ = t;
}
else
{
// Add the new task to the end of the list
// * t->next will point to the current head
// * t->prev will point to the current tail
// * head->prev will point to the new task
// * tail->next will point to the new task
ExSMTask *tail = head_->readyListPrev_;
exsm_assert(tail, "Ready list tail pointer should not be NULL");
t->readyListNext_ = head_;
t->readyListPrev_ = tail;
head_->readyListPrev_ = t;
tail->readyListNext_ = t;
}
}
void ExSMReadyList::remove(ExSMTask *t)
{
EXSM_TRACE(EXSM_TRACE_THR_ALL, "READY LIST REMOVE %p", t);
// Get pointers to the next and prev neighbors
ExSMTask *next = t->readyListNext_;
ExSMTask *prev = t->readyListPrev_;
exsm_assert(head_, "Ready list should not be NULL");
exsm_assert(next && prev, "Ready list neighbors should not be NULL");
// Clear pointers in the task being removed
t->readyListNext_ = NULL;
t->readyListPrev_ = NULL;
if (next == t)
{
// If the task was its own neighbor, that means it was the only
// element in the list. The list now becomes empty.
head_ = NULL;
}
else
{
// Update pointers in the neighbors
next->readyListPrev_ = prev;
prev->readyListNext_ = next;
// If the task was the first element, head_ will now point to the
// next neighbor
if (head_ == t)
head_ = next;
}
}
ExSMTask *ExSMReadyList::getFirst()
{
return head_;
}