summaryrefslogtreecommitdiff
path: root/include/android/metadata
AgeCommit message (Expand)Author
2019-08-12include: android: Add SPDX tagsJacopo Mondi
2019-08-12include: android: Add Android headers from CrosJacopo Mondi
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * signal.cpp - Signal & slot implementation
 */

#include <libcamera/signal.h>

#include "libcamera/internal/thread.h"

/**
 * \file signal.h
 * \brief Signal & slot implementation
 */

namespace libcamera {

namespace {

/*
 * Mutex to protect the SignalBase::slots_ and Object::signals_ lists. If lock
 * contention needs to be decreased, this could be replaced with locks in
 * Object and SignalBase, or with a mutex pool.
 */
Mutex signalsLock;

} /* namespace */

void SignalBase::connect(BoundMethodBase *slot)
{
	MutexLocker locker(signalsLock);

	Object *object = slot->object();
	if (object)
		object->connect(this);
	slots_.push_back(slot);
}

void SignalBase::disconnect(Object *object)
{
	disconnect([object](SlotList::iterator &iter) {
		return (*iter)->match(object);
	});
}

void SignalBase::disconnect(std::function<bool(SlotList::iterator &)> match)
{
	MutexLocker locker(signalsLock);

	for (auto iter = slots_.begin(); iter != slots_.end(); ) {
		if (match(iter)) {
			Object *object = (*iter)->object();
			if (object)
				object->disconnect(this);

			delete *iter;
			iter = slots_.erase(iter);
		} else {
			++iter;
		}
	}
}

SignalBase::SlotList SignalBase::slots()
{
	MutexLocker locker(signalsLock);
	return slots_;
}

/**
 * \class Signal
 * \brief Generic signal and slot communication mechanism
 *
 * Signals and slots are a language construct aimed at communication between
 * objects through the observer pattern without the need for boilerplate code.
 * See http://doc.qt.io/qt-5/signalsandslots.html for more information.
 *
 * Signals model events that can be observed from objects unrelated to the event
 * source. Slots are functions that are called in response to a signal. Signals
 * can be connected to and disconnected from slots dynamically at runtime. When
 * a signal is emitted, all connected slots are called sequentially in the order
 * they have been connected.
 *
 * Signals are defined with zero, one or more typed parameters. They are emitted
 * with a value for each of the parameters, and those values are passed to the
 * connected slots.
 *
 * Slots are normal static or class member functions. In order to be connected
 * to a signal, their signature must match the signal type (taking the same
 * arguments as the signal and returning void).
 *
 * Connecting a signal to a slot results in the slot being called with the
 * arguments passed to the emit() function when the signal is emitted. Multiple
 * slots can be connected to the same signal, and multiple signals can connected
 * to the same slot. Duplicate connections between a signal and a slot are
 * allowed and result in the slot being called multiple times for the same
 * signal emission.
 *
 * When a slot belongs to an instance of the Object class, the slot is called
 * in the context of the thread that the object is bound to. If the signal is
 * emitted from the same thread, the slot will be called synchronously, before
 * Signal::emit() returns. If the signal is emitted from a different thread,
 * the slot will be called asynchronously from the object's thread's event
 * loop, after the Signal::emit() method returns, with a copy of the signal's
 * arguments. The emitter shall thus ensure that any pointer or reference
 * passed through the signal will remain valid after the signal is emitted.
 */

/**
 * \fn Signal::connect(T *object, R (T::*func)(Args...))
 * \brief Connect the signal to a member function slot
 * \param[in] object The slot object pointer
 * \param[in] func The slot member function
 *
 * If the typename T inherits from Object, the signal will be automatically
 * disconnected from the \a func slot of \a object when \a object is destroyed.
 * Otherwise the caller shall disconnect signals manually before destroying \a
 * object.
 *
 * \context This function is \threadsafe.
 */

/**
 * \fn Signal::connect(R (*func)(Args...))
 * \brief Connect the signal to a static function slot
 * \param[in] func The slot static function
 *
 * \context This function is \threadsafe.
 */

/**
 * \fn Signal::disconnect()
 * \brief Disconnect the signal from all slots
 *
 * \context This function is \threadsafe.
 */

/**
 * \fn Signal::disconnect(T *object)
 * \brief Disconnect the signal from all slots of the \a object
 * \param[in] object The object pointer whose slots to disconnect
 *
 * \context This function is \threadsafe.
 */

/**
 * \fn Signal::disconnect(T *object, R (T::*func)(Args...))
 * \brief Disconnect the signal from the \a object slot member function \a func
 * \param[in] object The object pointer whose slots to disconnect
 * \param[in] func The slot member function to disconnect
 *
 * \context This function is \threadsafe.
 */

/**
 * \fn Signal::disconnect(R (*func)(Args...))
 * \brief Disconnect the signal from the slot static function \a func
 * \param[in] func The slot static function to disconnect
 *
 * \context This function is \threadsafe.
 */

/**
 * \fn Signal::emit(Args... args)
 * \brief Emit the signal and call all connected slots
 * \param args The arguments passed to the connected slots
 *
 * Emitting a signal calls all connected slots synchronously and sequentially in
 * the order the slots have been connected. The arguments passed to the emit()
 * function are passed to the slot functions unchanged. If a slot modifies one
 * of the arguments (when passed by pointer or reference), the modification is
 * thus visible to all subsequently called slots.
 *
 * This function is not \threadsafe, but thread-safety is guaranteed against
 * concurrent connect() and disconnect() calls.
 */

} /* namespace libcamera */