| Index: media/base/simple_state_machine.h
|
| diff --git a/media/base/simple_state_machine.h b/media/base/simple_state_machine.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e8aaaba56c7dc78af3bdd11f525f3be7ae4c7839
|
| --- /dev/null
|
| +++ b/media/base/simple_state_machine.h
|
| @@ -0,0 +1,92 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef MEDIA_BASE_SIMPLE_STATE_MACHINE_H_
|
| +#define MEDIA_BASE_SIMPLE_STATE_MACHINE_H_
|
| +
|
| +#include <tuple>
|
| +#include <type_traits>
|
| +
|
| +#include "base/memory/ref_counted.h"
|
| +#include "media/base/media_export.h"
|
| +#include "media/base/state_machine.h"
|
| +
|
| +namespace media {
|
| +
|
| +// Convenient template for state machines that have all of their state provided
|
| +// during construction. Provides storage for each of the states, registers
|
| +// them with StateMachine, and provides a getter for them.
|
| +// |StateTypes| should be the raw type for a State subclass. These must be
|
| +// unique right now, unfortunately, for the provided Get template to work. We
|
| +// could work around this with an optional ordinal parameter in the getter.
|
| +template <typename... StateTypes>
|
| +class SimpleStateMachine : public StateMachine {
|
| + public:
|
| + SimpleStateMachine(scoped_refptr<StateTypes>... states) : states_(states...) {
|
| + // Register all states with StateMachine.
|
| + RegisterStates<0>();
|
| + }
|
| +
|
| + // Return the state of type |T|.
|
| + template <typename T>
|
| + T* Get() const {
|
| + return FindElement<0, T>();
|
| + }
|
| +
|
| + private:
|
| + typedef std::tuple<scoped_refptr<StateTypes>...> states_t;
|
| + states_t states_;
|
| +
|
| + // Specialization to do nothing if we're asking for a state by index
|
| + // that's more than we have.
|
| + template <size_t pos>
|
| + typename std::enable_if<pos >= std::tuple_size<states_t>::value>::type
|
| + RegisterStates() {}
|
| +
|
| + // Specialization to register the |pos|-th state, and recurse to the
|
| + // next one.
|
| + template <size_t pos>
|
| + typename std::enable_if <
|
| + pos<std::tuple_size<states_t>::value>::type RegisterStates() {
|
| + UsingState(std::get<pos>(states_));
|
| + RegisterStates<pos + 1>();
|
| + }
|
| +
|
| + // Check for type equality.
|
| + // TODO: there has to be a better way. rewrite.
|
| + template <typename T1, typename T2>
|
| + struct is_same : std::false_type {};
|
| + template <typename T>
|
| + struct is_same<T, T> : std::true_type {};
|
| +
|
| + // When the element at |pos| is a scoped_refptr to |T|, return it as a
|
| + // raw pointer. If we wanted to support duplicate types, then we should
|
| + // also take an ordinal. If it's zero, then we return, else we recurse
|
| + // on |pos+1| and |ordinal-1|.
|
| + template <size_t pos, typename T>
|
| + typename std::enable_if <
|
| + pos<std::tuple_size<states_t>::value &&
|
| + is_same<typename std::tuple_element<pos, states_t>::type,
|
| + scoped_refptr<T>>::value,
|
| + T*>::type
|
| + FindElement() const {
|
| + return std::get<pos>(states_).get();
|
| + }
|
| +
|
| + // Continue searching for an element of type |scoped_refptr<T>| if the
|
| + // |pos|-th element doesn't match.
|
| + template <size_t pos, typename T>
|
| + typename std::enable_if <
|
| + pos<std::tuple_size<states_t>::value &&
|
| + !is_same<typename std::tuple_element<pos, states_t>::type,
|
| + scoped_refptr<T>>::value,
|
| + T*>::type
|
| + FindElement() const {
|
| + return FindElement<pos + 1, T>();
|
| + }
|
| +};
|
| +
|
| +} // namespace media
|
| +
|
| +#endif // MEDIA_BASE_SIMPLE_STATE_MACHINE_H_
|
|
|