<commit_before>/*
* File:   chain_queue.hpp
* Author: Barath Kannan
* This is an unbounded multi-producer multi-consumer queue.
* It can also be used as any combination of single-producer and single-consumer
* queues for additional performance gains in those contexts. The queue is implemented
* as a linked list, where nodes are stored in a freelist after being dequeued.
* Enqueue operations will either acquire items from the freelist or allocate a
* new node if none are available.
* Created on 27 August 2016, 11:30 PM
*/

#ifndef BK_CONQ_CHAINQUEUE_HPP
#define BK_CONQ_CHAINQUEUE_HPP

#include <atomic>
#include <thread>
#include <vector>
#include <array>
#include <memory>
#include <iostream>
#include <bk_conq/unbounded_queue.hpp>

namespace bk_conq {

	template<typename T>
	class chain_queue : public unbounded_queue<T, chain_queue<T>> {
		friend unbounded_queue<T, chain_queue<T>>;
		static const size_t BLOCK_SIZE = 1024;
	public:
		chain_queue() {
			auto hnode = std::make_unique<list_node_t>();
			auto flnode = std::make_unique<list_node_t>();
			auto ipnode = std::make_unique<list_node_t>();

			_head.store(hnode.get());
			_tail.store(_head.load(std::memory_order_relaxed), std::memory_order_relaxed);
			_free_list_head.store(flnode.get());
			_free_list_tail.store(_free_list_head.load(std::memory_order_relaxed), std::memory_order_relaxed);
			_in_progress_head.store(ipnode.get());
			_in_progress_tail.store(_in_progress_head.load(std::memory_order_relaxed), std::memory_order_relaxed);

			storage_node_t *store = new storage_node_t(std::move(hnode));
			storage_node_t* prev_head = _storage_head.exchange(store, std::memory_order_acq_rel);
			prev_head->next.store(store, std::memory_order_release);

			store = new storage_node_t(std::move(flnode));
			prev_head = _storage_head.exchange(store, std::memory_order_acq_rel);
			prev_head->next.store(store, std::memory_order_release);

			store = new storage_node_t(std::move(ipnode));
			prev_head = _storage_head.exchange(store, std::memory_order_acq_rel);
			prev_head->next.store(store, std::memory_order_release);
		}

		virtual ~chain_queue() {
			storage_node_t* tail = _storage_tail.load(std::memory_order_relaxed);
			storage_node_t* next = tail->next.load(std::memory_order_relaxed);
			for (storage_node_t* next = tail->next.load(std::memory_order_relaxed); next != nullptr; ) {
				tail = next;
				next = next->next.load(std::memory_order_relaxed);
				delete tail;
			}
		}

		chain_queue(const chain_queue&) = delete;
		void operator=(const chain_queue&) = delete;

	protected:
		template <typename R>
		void sp_enqueue_impl(R&& input) {
			list_node_t *node = acquire_or_allocate(std::forward<R>(input));
			if (!node) return;
			_head.load(std::memory_order_relaxed)->next.store(node, std::memory_order_release);
			_head.store(node, std::memory_order_relaxed);
		}

		template <typename R>
		void mp_enqueue_impl(R&& input) {
			list_node_t *node = acquire_or_allocate(std::forward<R>(input));
			if (!node) return;
			list_node_t* prev_head = _head.exchange(node, std::memory_order_acq_rel);
			prev_head->next.store(node, std::memory_order_release);
		}

		bool sc_dequeue_impl(T& output) {
			list_node_t* tail = _tail.load(std::memory_order_relaxed);
			return dequeue_common(tail, output);
		}

		//spin on dequeue contention
		bool mc_dequeue_impl(T& output) {
			list_node_t *tail;
			for (tail = _tail.exchange(nullptr, std::memory_order_acq_rel); !tail; tail = _tail.exchange(nullptr, std::memory_order_acq_rel)) {
				std::this_thread::yield();
			}
			return dequeue_common(tail, output);
		}

		//return false on dequeue contention
		bool mc_dequeue_uncontended_impl(T& output) {
			list_node_t *tail = _tail.exchange(nullptr, std::memory_order_acq_rel);
			if (!tail) return false;
			return dequeue_common(tail, output);
		}

	private:

		struct list_node_t {
			std::array<T, BLOCK_SIZE> data;
			std::atomic<list_node_t*> next{ nullptr };

			size_t indx{ 0 };
			list_node_t() {}
			template <typename R>
			bool put_get_full(R&& item) {
				data[indx] = std::forward<R>(item);
				return (++indx == BLOCK_SIZE);
			}
		};

		struct storage_node_t {
			std::unique_ptr<list_node_t> node;
			std::atomic<storage_node_t*> next{ nullptr };
			storage_node_t(std::unique_ptr<list_node_t> n) : node(std::move(n)) {};
			storage_node_t() {}
		};

		void list_enqueue(list_node_t* item, std::atomic<list_node_t*>& head) {
			item->next.store(nullptr, std::memory_order_relaxed);
			list_node_t * prev_head = head.exchange(item, std::memory_order_acq_rel);
			prev_head->next.store(item, std::memory_order_release);
		}

		list_node_t* list_dequeue(std::atomic<list_node_t*>& tail) {
			list_node_t *item;
			for (item = tail.exchange(nullptr, std::memory_order_acq_rel); !item; item = tail.exchange(nullptr, std::memory_order_acq_rel)) {
				std::this_thread::yield();
			}
			list_node_t* next = item->next.load(std::memory_order_acquire);
			if (!next) {
				tail.store(item, std::memory_order_release);
				return nullptr;
			}
			tail.store(next, std::memory_order_release);
			return item;
		}

		bool dequeue_common(list_node_t* tail, T& output) {
			//get item directly from tail
			if (tail->indx != 0) { //success
				output = std::move(tail->data[--tail->indx]);
				if (tail->indx == 0) { //if we are now empty
					list_node_t *next = tail->next.load(std::memory_order_acquire);
					if (next) { //we only want to progress if tail->next is valid
						_tail.store(next, std::memory_order_release);
						freelist_enqueue(tail);
						return true;
					}
				}
				//either more elements or next node is nullptr so can't progress
				_tail.store(tail, std::memory_order_release);
				return true;
			}

			//nothing in tail, go next
			list_node_t *next = tail->next.load(std::memory_order_acquire);
			if (!next) {
				//restore the tail so that other dequeue operations can progress
				_tail.store(tail, std::memory_order_release);
				return try_get_from_inprogress(output);
			}
			freelist_enqueue(tail);
			return dequeue_common(next, output);
		}

		void freelist_enqueue(list_node_t *item) {
			list_enqueue(item, _free_list_head);
		}

		list_node_t* freelist_try_dequeue() {
			return list_dequeue(_free_list_tail);
		}

		void inprogress_enqueue(list_node_t *item) {
			list_enqueue(item, _in_progress_head);
		}

		list_node_t* inprogress_try_dequeue() {
			return list_dequeue(_in_progress_tail);
		}

		bool try_get_from_inprogress_tail(T& output) {
			list_node_t* item = _in_progress_tail.load(std::memory_order_relaxed);
			if (!item) return false;
			for (item = _in_progress_tail.exchange(nullptr, std::memory_order_acq_rel); !item; item = _in_progress_tail.exchange(nullptr, std::memory_order_acq_rel)) {
				std::this_thread::yield();
			}
			if (item->indx != 0) { //success
				output = std::move(item->data[--item->indx]);
				if (item->indx == 0) { //if we are now empty
					list_node_t *next = item->next.load(std::memory_order_acquire);
					if (next) { //we only want to progress if tail->next is valid
						_in_progress_tail.store(next, std::memory_order_release);
						freelist_enqueue(item);
						return true;
					}
				}
				//either more elements or next node is nullptr so can't progress
				_in_progress_tail.store(item, std::memory_order_release);
				return true;
			}
			_in_progress_tail.store(item, std::memory_order_release);

			return false;
		}

		bool try_get_from_inprogress(T& output) {
			list_node_t* item = _in_progress_tail.load(std::memory_order_relaxed);
			if (!item) return false;
			item = inprogress_try_dequeue();
			if (item == nullptr) {
				return try_get_from_inprogress_tail(output);
			}

			if (item->indx != 0) { //success
				output = std::move(item->data[--item->indx]);
				if (item->indx == 0) { //if we are now empty
					freelist_enqueue(item);
				}
				else {
					item->next.store(nullptr, std::memory_order_relaxed);
					list_node_t* prev_head = _head.exchange(item, std::memory_order_acq_rel);
					prev_head->next.store(item, std::memory_order_release);
				}
				return true;
			}
			freelist_enqueue(item);
			return try_get_from_inprogress(output);
		}

		list_node_t* allocate() {
			auto up = std::make_unique<list_node_t>();
			auto ret = up.get();
			//store the node on the storage queue for retrieval later
			storage_node_t *store = new storage_node_t(std::move(up));
			storage_node_t* prev_head = _storage_head.exchange(store, std::memory_order_acq_rel);
			prev_head->next.store(store, std::memory_order_release);

			return ret;
		}

		template<typename R>
		list_node_t *acquire_or_allocate(R&& input) {
			list_node_t* node = inprogress_try_dequeue(); //try get space from the in progress enqueue operations
			if (!node) node = freelist_try_dequeue();//attempt to recycle previously used storage
			if (!node) node = allocate(); //allocate new storage
			if (node->put_get_full(std::forward<R>(input))) {
				node->next.store(nullptr, std::memory_order_relaxed);
				return node;
			}
			inprogress_enqueue(node);
			return nullptr;
		}

		std::atomic<list_node_t*>	_last_progress;
		std::atomic<list_node_t*>   _head;
		std::atomic<list_node_t*>   _free_list_tail;
		std::array<char, 64>	    _padding0;
		std::atomic<list_node_t*>   _tail;
		std::atomic<list_node_t*>   _free_list_head;
		std::array<char, 64>	    _padding2;
		std::atomic<list_node_t*>   _in_progress_head;
		std::atomic<storage_node_t*> _storage_head{ new storage_node_t };
		std::atomic<list_node_t*>   _in_progress_tail;
		std::atomic<storage_node_t*> _storage_tail{ _storage_head.load(std::memory_order_relaxed) };
	};
}//namespace bk_conq

#endif /* BK_CONQ_CHAINQUEUE_HPP */
<commit_msg>remove storage_node linked list, can release resources manually on each list<commit_after>/*
* File:   chain_queue.hpp
* Author: Barath Kannan
* This is an unbounded multi-producer multi-consumer queue.
* It can also be used as any combination of single-producer and single-consumer
* queues for additional performance gains in those contexts. The queue is implemented
* as a linked list, where nodes are stored in a freelist after being dequeued.
* Enqueue operations will either acquire items from the freelist or allocate a
* new node if none are available.
* Created on 27 August 2016, 11:30 PM
*/

#ifndef BK_CONQ_CHAINQUEUE_HPP
#define BK_CONQ_CHAINQUEUE_HPP

#include <atomic>
#include <thread>
#include <vector>
#include <array>
#include <memory>
#include <iostream>
#include <bk_conq/unbounded_queue.hpp>

namespace bk_conq {

	template<typename T>
	class chain_queue : public unbounded_queue<T, chain_queue<T>> {
		friend unbounded_queue<T, chain_queue<T>>;
		static const size_t BLOCK_SIZE = 1024;
	public:
		chain_queue() {
            auto hnode = new list_node_t;
			auto flnode = new list_node_t;
			auto ipnode = new list_node_t;

			_head.store(hnode);
			_tail.store(_head.load(std::memory_order_relaxed), std::memory_order_relaxed);
			_free_list_head.store(flnode);
			_free_list_tail.store(_free_list_head.load(std::memory_order_relaxed), std::memory_order_relaxed);
			_in_progress_head.store(ipnode);
			_in_progress_tail.store(_in_progress_head.load(std::memory_order_relaxed), std::memory_order_relaxed);
		}

		virtual ~chain_queue() {
            list_node_t* next;
            list_node_t* tail = _tail.load(std::memory_order_relaxed);

            for (next = tail->next.load(std::memory_order_relaxed); next != nullptr; ) {
                tail = next;
                next = next->next.load(std::memory_order_relaxed);
                delete tail;
            }
            delete _tail.load();

            tail = _free_list_tail.load(std::memory_order_relaxed);
            for (next = tail->next.load(std::memory_order_relaxed); next != nullptr; ) {
                tail = next;
                next = next->next.load(std::memory_order_relaxed);
                delete tail;
            }
            delete _free_list_tail.load();

            tail = _in_progress_tail.load(std::memory_order_relaxed);
            for (next = tail->next.load(std::memory_order_relaxed); next != nullptr; ) {
                tail = next;
                next = next->next.load(std::memory_order_relaxed);
                delete tail;
            }
            delete _in_progress_tail.load();

		}

		chain_queue(const chain_queue&) = delete;
		void operator=(const chain_queue&) = delete;

	protected:
		template <typename R>
		void sp_enqueue_impl(R&& input) {
			list_node_t *node = acquire_or_allocate(std::forward<R>(input));
			if (!node) return;
			_head.load(std::memory_order_relaxed)->next.store(node, std::memory_order_release);
			_head.store(node, std::memory_order_relaxed);
		}

		template <typename R>
		void mp_enqueue_impl(R&& input) {
			list_node_t *node = acquire_or_allocate(std::forward<R>(input));
			if (!node) return;
			list_node_t* prev_head = _head.exchange(node, std::memory_order_acq_rel);
			prev_head->next.store(node, std::memory_order_release);
		}

		bool sc_dequeue_impl(T& output) {
			list_node_t* tail = _tail.load(std::memory_order_relaxed);
			return dequeue_common(tail, output);
		}

		//spin on dequeue contention
		bool mc_dequeue_impl(T& output) {
			list_node_t *tail;
			for (tail = _tail.exchange(nullptr, std::memory_order_acq_rel); !tail; tail = _tail.exchange(nullptr, std::memory_order_acq_rel)) {
				std::this_thread::yield();
			}
			return dequeue_common(tail, output);
		}

		//return false on dequeue contention
		bool mc_dequeue_uncontended_impl(T& output) {
			list_node_t *tail = _tail.exchange(nullptr, std::memory_order_acq_rel);
			if (!tail) return false;
			return dequeue_common(tail, output);
		}

	private:

		struct list_node_t {
			std::array<T, BLOCK_SIZE> data;
			std::atomic<list_node_t*> next{ nullptr };

			size_t indx{ 0 };
			list_node_t() {}
			template <typename R>
			bool put_get_full(R&& item) {
				data[indx] = std::forward<R>(item);
				return (++indx == BLOCK_SIZE);
			}
		};

		void list_enqueue(list_node_t* item, std::atomic<list_node_t*>& head) {
			item->next.store(nullptr, std::memory_order_relaxed);
			list_node_t * prev_head = head.exchange(item, std::memory_order_acq_rel);
			prev_head->next.store(item, std::memory_order_release);
		}

		list_node_t* list_dequeue(std::atomic<list_node_t*>& tail) {
			list_node_t *item;
			for (item = tail.exchange(nullptr, std::memory_order_acq_rel); !item; item = tail.exchange(nullptr, std::memory_order_acq_rel)) {
				std::this_thread::yield();
			}
			list_node_t* next = item->next.load(std::memory_order_acquire);
			if (!next) {
				tail.store(item, std::memory_order_release);
				return nullptr;
			}
			tail.store(next, std::memory_order_release);
			return item;
		}

		bool dequeue_common(list_node_t* tail, T& output) {
			//get item directly from tail
			if (tail->indx != 0) { //success
				output = std::move(tail->data[--tail->indx]);
				if (tail->indx == 0) { //if we are now empty
					list_node_t *next = tail->next.load(std::memory_order_acquire);
					if (next) { //we only want to progress if tail->next is valid
						_tail.store(next, std::memory_order_release);
						freelist_enqueue(tail);
						return true;
					}
				}
				//either more elements or next node is nullptr so can't progress
				_tail.store(tail, std::memory_order_release);
				return true;
			}

			//nothing in tail, go next
			list_node_t *next = tail->next.load(std::memory_order_acquire);
			if (!next) {
				//restore the tail so that other dequeue operations can progress
				_tail.store(tail, std::memory_order_release);
				return try_get_from_inprogress(output);
			}
			freelist_enqueue(tail);
			return dequeue_common(next, output);
		}

		void freelist_enqueue(list_node_t *item) {
			list_enqueue(item, _free_list_head);
		}

		list_node_t* freelist_try_dequeue() {
			return list_dequeue(_free_list_tail);
		}

		void inprogress_enqueue(list_node_t *item) {
			list_enqueue(item, _in_progress_head);
		}

		list_node_t* inprogress_try_dequeue() {
			return list_dequeue(_in_progress_tail);
		}

		bool try_get_from_inprogress_tail(T& output) {
			list_node_t* item = _in_progress_tail.load(std::memory_order_relaxed);
			if (!item) return false;
			for (item = _in_progress_tail.exchange(nullptr, std::memory_order_acq_rel); !item; item = _in_progress_tail.exchange(nullptr, std::memory_order_acq_rel)) {
				std::this_thread::yield();
			}
			if (item->indx != 0) { //success
				output = std::move(item->data[--item->indx]);
				if (item->indx == 0) { //if we are now empty
					list_node_t *next = item->next.load(std::memory_order_acquire);
					if (next) { //we only want to progress if tail->next is valid
						_in_progress_tail.store(next, std::memory_order_release);
						freelist_enqueue(item);
						return true;
					}
				}
				//either more elements or next node is nullptr so can't progress
				_in_progress_tail.store(item, std::memory_order_release);
				return true;
			}
			_in_progress_tail.store(item, std::memory_order_release);

			return false;
		}

		bool try_get_from_inprogress(T& output) {
			list_node_t* item = _in_progress_tail.load(std::memory_order_relaxed);
			if (!item) return false;
			item = inprogress_try_dequeue();
			if (item == nullptr) {
				return try_get_from_inprogress_tail(output);
			}

			if (item->indx != 0) { //success
				output = std::move(item->data[--item->indx]);
				if (item->indx == 0) { //if we are now empty
					freelist_enqueue(item);
				}
				else {
					item->next.store(nullptr, std::memory_order_relaxed);
					list_node_t* prev_head = _head.exchange(item, std::memory_order_acq_rel);
					prev_head->next.store(item, std::memory_order_release);
				}
				return true;
			}
			freelist_enqueue(item);
			return try_get_from_inprogress(output);
		}

		list_node_t* allocate() {
			return new list_node_t;
		}

		template<typename R>
		list_node_t *acquire_or_allocate(R&& input) {
			list_node_t* node = inprogress_try_dequeue(); //try get space from the in progress enqueue operations
			if (!node) node = freelist_try_dequeue();//attempt to recycle previously used storage
			if (!node) node = allocate(); //allocate new storage
			if (node->put_get_full(std::forward<R>(input))) {
				node->next.store(nullptr, std::memory_order_relaxed);
				return node;
			}
			inprogress_enqueue(node);
			return nullptr;
		}

        std::atomic<list_node_t*>   _in_progress_head;
        std::atomic<list_node_t*>   _head;
		std::atomic<list_node_t*>   _free_list_tail;
		std::array<char, 64>	    _padding1;
		std::atomic<list_node_t*>   _tail;
		std::atomic<list_node_t*>   _free_list_head;
        std::array<char, 64>	    _padding2;
		std::atomic<list_node_t*>   _in_progress_tail;
	};
}//namespace bk_conq

#endif /* BK_CONQ_CHAINQUEUE_HPP */
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "searchiterator.h"
#include <vespa/searchlib/index/docidandfeatures.h>
#include <vespa/vespalib/objects/objectdumper.h>
#include <vespa/vespalib/objects/visit.h>
#include <vespa/vespalib/util/classname.h>
#include <vespa/searchlib/common/bitvector.h>

namespace search {
namespace queryeval {

SearchIterator::SearchIterator() :
    _docid(0),
    _endid(0)
{ }

void
SearchIterator::initRange(uint32_t beginid, uint32_t endid)
{
    _docid = beginid - 1;
    _endid = endid;
}

BitVector::UP
SearchIterator::get_hits(uint32_t begin_id)
{
    BitVector::UP result(BitVector::create(begin_id, getEndId()));
    uint32_t docid = std::max(begin_id, getDocId());
    while (!isAtEnd(docid)) {
        if (seek(docid)) {
            result->setBit(docid);
        }
        docid = std::max(docid + 1, getDocId());
    }
    return result;
}

SearchIterator::UP
SearchIterator::andWith(UP filter, uint32_t estimate)
{
    (void) estimate;
    return filter;
}

void
SearchIterator::or_hits_into(BitVector &result, uint32_t begin_id)
{
    uint32_t docid = std::max(begin_id, getDocId());
    while (!isAtEnd(docid)) {
        docid = result.getNextFalseBit(docid);
        if (!isAtEnd(docid) && seek(docid)) {
            result.setBit(docid);
        }
        docid = std::max(docid + 1, getDocId());
    }
}

void
SearchIterator::and_hits_into(BitVector &result, uint32_t begin_id)
{
    uint32_t docidA = begin_id - 1;
    uint32_t docidB = result.getNextTrueBit(begin_id);
    while (!isAtEnd(docidB)) {
        if (docidA < docidB) {
            if (seek(docidB)) {
                docidA = docidB;
            } else {
                docidA = std::max(docidB+1, getDocId());
            }
        } else if (docidA > docidB) {
            result.clearInterval(docidB, docidA);
            docidB = (! isAtEnd(docidA)) ? result.getNextTrueBit(docidA) : getEndId();
        } else {
            docidB = result.getNextTrueBit(docidB+1);
        }
    }
}

vespalib::string
SearchIterator::asString() const
{
    vespalib::ObjectDumper dumper;
    visit(dumper, "", this);
    return dumper.toString();
}

vespalib::string
SearchIterator::getClassName() const
{
    return vespalib::getClassName(*this);
}

void
SearchIterator::visitMembers(vespalib::ObjectVisitor &visitor) const
{
    visit(visitor, "docid", _docid);
    visit(visitor, "endid", _endid);
}

namespace {

using Children = SearchIterator::Children;

BitVector::UP
andIterators(BitVector::UP result, const Children &children, uint32_t begin_id, bool select_bitvector) {
    for (SearchIterator *child : children) {
        if (child->isBitVector() == select_bitvector) {
            if (!result) {
                result = child->get_hits(begin_id);
            } else {
                child->and_hits_into(*result, begin_id);
            }
        }
    }
    return result;
}

void
andIterators(BitVector & result, const Children &children, uint32_t begin_id, bool select_bitvector) {
    for (SearchIterator *child : children) {
        if (child->isBitVector() == select_bitvector) {
            child->and_hits_into(result, begin_id);
        }
    }
}

template<typename IT>
BitVector::UP
orIterators(BitVector::UP result, IT begin, IT end, uint32_t begin_id, bool select_bitvector) {
    for (IT it(begin); it != end; ++it) {
        auto & child = *it;
        if (child->isBitVector() == select_bitvector) {
            if (!result) {
                result = child->get_hits(begin_id);
            } else {
                child->or_hits_into(*result, begin_id);
            }
        }
    }
    return result;
}

template<typename IT>
void
orIterators(BitVector & result, IT begin, IT end, uint32_t begin_id, bool select_bitvector) {
    for (IT it(begin); it != end; ++it) {
        auto & child = *it;
        if (child->isBitVector() == select_bitvector) {
            child->or_hits_into(result, begin_id);
        }
    }
}

}

BitVector::UP
SearchIterator::andChildren(BitVector::UP result, const Children &children, uint32_t begin_id) {
    return andIterators(andIterators(std::move(result), children, begin_id, true), children, begin_id, false);
}

void
SearchIterator::andChildren(BitVector & result, const Children &children, uint32_t begin_id) {
    andIterators(result, children, begin_id, true);
    andIterators(result, children, begin_id, false);
}

BitVector::UP
SearchIterator::andChildren(const Children &children, uint32_t begin_id) {
    return andChildren(BitVector::UP(), children, begin_id);
}

template<typename IT>
BitVector::UP
SearchIterator::orChildren(BitVector::UP result, IT from, IT to, uint32_t begin_id) {
    return orIterators(orIterators(std::move(result), from, to, begin_id, true),
                       from, to, begin_id, false);
}

template<typename IT>
void SearchIterator::orChildren(BitVector & result, IT from, IT to, uint32_t begin_id) {
    orIterators(result, from, to, begin_id, true);
    orIterators(result, from, to, begin_id, false);
}

template<typename IT>
BitVector::UP
SearchIterator::orChildren(IT from, IT to, uint32_t begin_id) {
    return orChildren(BitVector::UP(), from, to, begin_id);
}

template BitVector::UP SearchIterator::orChildren(Children::const_iterator from, Children::const_iterator to, uint32_t begin_id);
template BitVector::UP SearchIterator::orChildren(OwnedChildren::const_iterator from, OwnedChildren::const_iterator to, uint32_t begin_id);
template BitVector::UP SearchIterator::orChildren(BitVector::UP result, Children::const_iterator from, Children::const_iterator to, uint32_t begin_id);
template BitVector::UP SearchIterator::orChildren(BitVector::UP result, OwnedChildren::const_iterator from, OwnedChildren::const_iterator to, uint32_t begin_id);
template void SearchIterator::orChildren(BitVector & result, Children::const_iterator from, Children::const_iterator to, uint32_t begin_id);
template void SearchIterator::orChildren(BitVector & result, OwnedChildren::const_iterator from, OwnedChildren::const_iterator to, uint32_t begin_id);

} // namespace queryeval
} // namespace search

//-----------------------------------------------------------------------------

void visit(vespalib::ObjectVisitor &self, const vespalib::string &name,
           const search::queryeval::SearchIterator *obj)
{
    if (obj != 0) {
        self.openStruct(name, obj->getClassName());
        obj->visitMembers(self);
        self.closeStruct();
    } else {
        self.visitNull(name);
    }
}

void visit(vespalib::ObjectVisitor &self, const vespalib::string &name,
           const search::queryeval::SearchIterator &obj)
{
    visit(self, name, &obj);
}
<commit_msg>Easy readability of merge loop.<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "searchiterator.h"
#include <vespa/searchlib/index/docidandfeatures.h>
#include <vespa/vespalib/objects/objectdumper.h>
#include <vespa/vespalib/objects/visit.h>
#include <vespa/vespalib/util/classname.h>
#include <vespa/searchlib/common/bitvector.h>

namespace search {
namespace queryeval {

SearchIterator::SearchIterator() :
    _docid(0),
    _endid(0)
{ }

void
SearchIterator::initRange(uint32_t beginid, uint32_t endid)
{
    _docid = beginid - 1;
    _endid = endid;
}

BitVector::UP
SearchIterator::get_hits(uint32_t begin_id)
{
    BitVector::UP result(BitVector::create(begin_id, getEndId()));
    uint32_t docid = std::max(begin_id, getDocId());
    while (!isAtEnd(docid)) {
        if (seek(docid)) {
            result->setBit(docid);
        }
        docid = std::max(docid + 1, getDocId());
    }
    return result;
}

SearchIterator::UP
SearchIterator::andWith(UP filter, uint32_t estimate)
{
    (void) estimate;
    return filter;
}

void
SearchIterator::or_hits_into(BitVector &result, uint32_t begin_id)
{
    uint32_t docid = std::max(begin_id, getDocId());
    while (!isAtEnd(docid)) {
        docid = result.getNextFalseBit(docid);
        if (!isAtEnd(docid) && seek(docid)) {
            result.setBit(docid);
        }
        docid = std::max(docid + 1, getDocId());
    }
}

void
SearchIterator::and_hits_into(BitVector &result, uint32_t begin_id)
{
    uint32_t docidA = begin_id - 1;
    uint32_t docidB = result.getNextTrueBit(begin_id);
    while (!isAtEnd(docidB) && !isAtEnd(docidA)) {
        if (docidA < docidB) {
            if (seek(docidB)) {
                docidA = docidB;
            } else {
                docidA = std::max(docidB+1, getDocId());
            }
        } else if (docidA > docidB) {
            result.clearInterval(docidB, docidA);
            docidB = result.getNextTrueBit(docidA);
        } else {
            docidB = result.getNextTrueBit(docidB+1);
        }
    }
    result.clearInterval(docidB, result.size());
}

vespalib::string
SearchIterator::asString() const
{
    vespalib::ObjectDumper dumper;
    visit(dumper, "", this);
    return dumper.toString();
}

vespalib::string
SearchIterator::getClassName() const
{
    return vespalib::getClassName(*this);
}

void
SearchIterator::visitMembers(vespalib::ObjectVisitor &visitor) const
{
    visit(visitor, "docid", _docid);
    visit(visitor, "endid", _endid);
}

namespace {

using Children = SearchIterator::Children;

BitVector::UP
andIterators(BitVector::UP result, const Children &children, uint32_t begin_id, bool select_bitvector) {
    for (SearchIterator *child : children) {
        if (child->isBitVector() == select_bitvector) {
            if (!result) {
                result = child->get_hits(begin_id);
            } else {
                child->and_hits_into(*result, begin_id);
            }
        }
    }
    return result;
}

void
andIterators(BitVector & result, const Children &children, uint32_t begin_id, bool select_bitvector) {
    for (SearchIterator *child : children) {
        if (child->isBitVector() == select_bitvector) {
            child->and_hits_into(result, begin_id);
        }
    }
}

template<typename IT>
BitVector::UP
orIterators(BitVector::UP result, IT begin, IT end, uint32_t begin_id, bool select_bitvector) {
    for (IT it(begin); it != end; ++it) {
        auto & child = *it;
        if (child->isBitVector() == select_bitvector) {
            if (!result) {
                result = child->get_hits(begin_id);
            } else {
                child->or_hits_into(*result, begin_id);
            }
        }
    }
    return result;
}

template<typename IT>
void
orIterators(BitVector & result, IT begin, IT end, uint32_t begin_id, bool select_bitvector) {
    for (IT it(begin); it != end; ++it) {
        auto & child = *it;
        if (child->isBitVector() == select_bitvector) {
            child->or_hits_into(result, begin_id);
        }
    }
}

}

BitVector::UP
SearchIterator::andChildren(BitVector::UP result, const Children &children, uint32_t begin_id) {
    return andIterators(andIterators(std::move(result), children, begin_id, true), children, begin_id, false);
}

void
SearchIterator::andChildren(BitVector & result, const Children &children, uint32_t begin_id) {
    andIterators(result, children, begin_id, true);
    andIterators(result, children, begin_id, false);
}

BitVector::UP
SearchIterator::andChildren(const Children &children, uint32_t begin_id) {
    return andChildren(BitVector::UP(), children, begin_id);
}

template<typename IT>
BitVector::UP
SearchIterator::orChildren(BitVector::UP result, IT from, IT to, uint32_t begin_id) {
    return orIterators(orIterators(std::move(result), from, to, begin_id, true),
                       from, to, begin_id, false);
}

template<typename IT>
void SearchIterator::orChildren(BitVector & result, IT from, IT to, uint32_t begin_id) {
    orIterators(result, from, to, begin_id, true);
    orIterators(result, from, to, begin_id, false);
}

template<typename IT>
BitVector::UP
SearchIterator::orChildren(IT from, IT to, uint32_t begin_id) {
    return orChildren(BitVector::UP(), from, to, begin_id);
}

template BitVector::UP SearchIterator::orChildren(Children::const_iterator from, Children::const_iterator to, uint32_t begin_id);
template BitVector::UP SearchIterator::orChildren(OwnedChildren::const_iterator from, OwnedChildren::const_iterator to, uint32_t begin_id);
template BitVector::UP SearchIterator::orChildren(BitVector::UP result, Children::const_iterator from, Children::const_iterator to, uint32_t begin_id);
template BitVector::UP SearchIterator::orChildren(BitVector::UP result, OwnedChildren::const_iterator from, OwnedChildren::const_iterator to, uint32_t begin_id);
template void SearchIterator::orChildren(BitVector & result, Children::const_iterator from, Children::const_iterator to, uint32_t begin_id);
template void SearchIterator::orChildren(BitVector & result, OwnedChildren::const_iterator from, OwnedChildren::const_iterator to, uint32_t begin_id);

} // namespace queryeval
} // namespace search

//-----------------------------------------------------------------------------

void visit(vespalib::ObjectVisitor &self, const vespalib::string &name,
           const search::queryeval::SearchIterator *obj)
{
    if (obj != 0) {
        self.openStruct(name, obj->getClassName());
        obj->visitMembers(self);
        self.closeStruct();
    } else {
        self.visitNull(name);
    }
}

void visit(vespalib::ObjectVisitor &self, const vespalib::string &name,
           const search::queryeval::SearchIterator &obj)
{
    visit(self, name, &obj);
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "labelpage.h"

#include <MLabel>
#include <MLayout>
#include <MLocale>
#include <MApplicationPage>
#include <MLinearLayoutPolicy>
#include <mdebug.h>

#include <mtextedit.h>
#include <mbutton.h>
#include <mlabelhighlighter.h>

LabelPage::LabelPage()
    : TemplatePage(TemplatePage::SimpleWidgets),
      simpleLabel(0),
      richLabel(0),
      ignoreClickAndLongPressCheckbox(0),
      ignoreClickAndLongPressLabel(0),
      phoneHighlighter(0),
      urlHighlighter(0),
      emailHighlighter(0),
      commonHighlighter(0)
{
}

LabelPage::~LabelPage()
{
    delete phoneHighlighter;
    delete emailHighlighter;
    delete urlHighlighter;
    delete commonHighlighter;
}

QString LabelPage::timedemoTitle()
{
    return "Label";
}

void LabelPage::createContent()
{
    TemplatePage::createContent();

    simpleLabel = new MLabel();
    simpleLabel->setObjectName("simpleLabel");
    simpleLabel->setStyleName(inv("CommonBodyText"));
    simpleLabel->setAlignment(Qt::AlignVCenter);
    containerPolicy->addItem(simpleLabel);

    richLabel = new MLabel();
    richLabel->setObjectName("richLabel");
    richLabel->setStyleName(inv("CommonBodyText"));

    richLabel->setAlignment(Qt::AlignTop);
    richLabel->setWordWrap(true);
    containerPolicy->addItem(richLabel);

    ignoreClickAndLongPressLabel = new MLabel;
    ignoreClickAndLongPressLabel->setTextElide(true);
    containerPolicy->addItem(ignoreClickAndLongPressLabel);

    ignoreClickAndLongPressCheckbox = new MButton;
    ignoreClickAndLongPressCheckbox->setViewType(MButton::checkboxType);
    ignoreClickAndLongPressCheckbox->setCheckable(true);
    ignoreClickAndLongPressCheckbox->setChecked(true);
    containerPolicy->addItem(ignoreClickAndLongPressCheckbox);

    QRegExp phoneregexp("[\\+]{0,1}(\\d{8,13}|[\\(][\\+]{0,1}\\d{2,}[\\)]*\\d{5,13}|\\d{2,6}[\\-]{1}\\d{2,13}[\\-]*\\d{3,13})",
                        Qt::CaseInsensitive);
    QRegExp emailregexp("([0-9A-Z]([-\\.\\w]*[0-9A-Z])*@([0-9A-Z][-\\w]*[0-9A-Z]\\.)+[A-Z]{2,9})",
                        Qt::CaseInsensitive);
    QRegExp urlregexp("[-\\w\\.]+://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?([-\\w\\.]+)(/([\\w/_\\.]*(\\?\\S+)?)?)?",
                      Qt::CaseInsensitive);
//    QRegExp url("https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?",
//                Qt::CaseInsensitive);

    MCommonLabelHighlighter *phone = new MCommonLabelHighlighter(phoneregexp);
    phone->setObjectName("phoneLabelHighlighter");
    MCommonLabelHighlighter *email = new MCommonLabelHighlighter(emailregexp);
    email->setObjectName("emailLabelHighlighter");
    MCommonLabelHighlighter *url = new MCommonLabelHighlighter(urlregexp);
    url->setObjectName("urlLabelHighlighter");

    connect(phone, SIGNAL(longPressed(QString)), this, SLOT(phoneNumberLongPressed(QString)));
    connect(phone, SIGNAL(clicked(QString)), this, SLOT(phoneNumberClicked(QString)));

    connect(email, SIGNAL(longPressed(QString)), this, SLOT(emailLongPressed(QString)));
    connect(email, SIGNAL(clicked(QString)), this, SLOT(emailClicked(QString)));

    connect(url, SIGNAL(longPressed(QString)), this, SLOT(urlLongPressed(QString)));
    connect(url, SIGNAL(clicked(QString)), this, SLOT(urlClicked(QString)));

    connect(ignoreClickAndLongPressCheckbox, SIGNAL(toggled(bool)), this, SLOT(enableOrDisableClickAndLongPressHandling(bool)));

    phoneHighlighter = phone;
    emailHighlighter = email;
    urlHighlighter = url;

    richLabel->addHighlighter(emailHighlighter);
    richLabel->addHighlighter(phoneHighlighter);
    richLabel->addHighlighter(urlHighlighter);

    retranslateUi();
}

void LabelPage::retranslateUi()
{
    //% "Labels"
    setTitle(qtTrId("xx_label_page_title"));
    if (!isContentCreated())
        return;
    //% "Simple Label is used mainly by other components, and it does "
    //% "not support any formatting or interaction.\n\n"
    //% "Rich Label supports multiple lines, HTML formatting and "
    //% "highlighting for links.\n\n"
    //% "All Labels can be aligned left, right or center and will be "
    //% "automatically truncated if the text does not fit inside "
    //% "the given area."
    infoLabel->setText("" + qtTrId("xx_label_page_info_label").replace('\n', "
"));
    //% "Simple Label"
    simpleLabel->setText(qtTrId("xx_simple_label"));
    //% "Rich Label bold, italic, "
    //% "http://www.nokia.com, +358401234567, fors.fagerstrom@email.com"
    richLabel->setText(qtTrId("xx_rich_label"));

    //% "Handle click and long press events:"
    ignoreClickAndLongPressLabel->setText(qtTrId("xx_label_page_handle_click_and_long_press_events"));

    update();
}

void LabelPage::phoneNumberLongPressed(const QString &link)
{
    mDebug("LabelPage::phoneNumberLongPressed()") << link;
}

void LabelPage::phoneNumberClicked(const QString &link)
{
    mDebug("LabelPage::phoneNumberClicked()") << link;
}

void LabelPage::emailLongPressed(const QString &link)
{
    mDebug("LabelPage::emailLongPressed()") << link;
}

void LabelPage::emailClicked(const QString &link)
{
    mDebug("LabelPage::emailClicked()") << link;
}

void LabelPage::urlLongPressed(const QString &link)
{
    mDebug("LabelPage::urlLongPressed()") << link;
}

void LabelPage::urlClicked(const QString &link)
{
    mDebug("LabelPage::urlClicked()") << link;
}

void LabelPage::enableOrDisableClickAndLongPressHandling(bool checked)
{
    phoneHighlighter->setIgnoreClickAndLongPressEvents(!checked);
    emailHighlighter->setIgnoreClickAndLongPressEvents(!checked);
    urlHighlighter->setIgnoreClickAndLongPressEvents(!checked);
}
<commit_msg>Changes: Add correct styling properties to the new checkbox. RevBy: Adrian Yanes<commit_after>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "labelpage.h"

#include <MLabel>
#include <MLayout>
#include <MLocale>
#include <MApplicationPage>
#include <MLinearLayoutPolicy>
#include <mdebug.h>

#include <mtextedit.h>
#include <mbutton.h>
#include <mlabelhighlighter.h>

LabelPage::LabelPage()
    : TemplatePage(TemplatePage::SimpleWidgets),
      simpleLabel(0),
      richLabel(0),
      ignoreClickAndLongPressCheckbox(0),
      ignoreClickAndLongPressLabel(0),
      phoneHighlighter(0),
      urlHighlighter(0),
      emailHighlighter(0),
      commonHighlighter(0)
{
}

LabelPage::~LabelPage()
{
    delete phoneHighlighter;
    delete emailHighlighter;
    delete urlHighlighter;
    delete commonHighlighter;
}

QString LabelPage::timedemoTitle()
{
    return "Label";
}

void LabelPage::createContent()
{
    TemplatePage::createContent();

    simpleLabel = new MLabel();
    simpleLabel->setObjectName("simpleLabel");
    simpleLabel->setStyleName(inv("CommonBodyText"));
    simpleLabel->setAlignment(Qt::AlignVCenter);
    containerPolicy->addItem(simpleLabel);

    richLabel = new MLabel();
    richLabel->setObjectName("richLabel");
    richLabel->setStyleName(inv("CommonBodyText"));

    richLabel->setAlignment(Qt::AlignTop);
    richLabel->setWordWrap(true);
    containerPolicy->addItem(richLabel);

    ignoreClickAndLongPressLabel = new MLabel;
    ignoreClickAndLongPressLabel->setObjectName("ignoreClickAndLongPressLabel");
    ignoreClickAndLongPressLabel->setStyleName(inv("CommonBodyText"));
    ignoreClickAndLongPressLabel->setWordWrap(true);
    containerPolicy->addItem(ignoreClickAndLongPressLabel);

    ignoreClickAndLongPressCheckbox = new MButton;
    ignoreClickAndLongPressCheckbox->setObjectName("ignoreClickAndLongPressCheckbox");
    ignoreClickAndLongPressCheckbox->setStyleName(inv("CommonCheckBox"));
    ignoreClickAndLongPressCheckbox->setViewType(MButton::checkboxType);
    ignoreClickAndLongPressCheckbox->setCheckable(true);
    ignoreClickAndLongPressCheckbox->setChecked(true);
    containerPolicy->addItem(ignoreClickAndLongPressCheckbox);

    QRegExp phoneregexp("[\\+]{0,1}(\\d{8,13}|[\\(][\\+]{0,1}\\d{2,}[\\)]*\\d{5,13}|\\d{2,6}[\\-]{1}\\d{2,13}[\\-]*\\d{3,13})",
                        Qt::CaseInsensitive);
    QRegExp emailregexp("([0-9A-Z]([-\\.\\w]*[0-9A-Z])*@([0-9A-Z][-\\w]*[0-9A-Z]\\.)+[A-Z]{2,9})",
                        Qt::CaseInsensitive);
    QRegExp urlregexp("[-\\w\\.]+://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?([-\\w\\.]+)(/([\\w/_\\.]*(\\?\\S+)?)?)?",
                      Qt::CaseInsensitive);
//    QRegExp url("https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?",
//                Qt::CaseInsensitive);

    MCommonLabelHighlighter *phone = new MCommonLabelHighlighter(phoneregexp);
    phone->setObjectName("phoneLabelHighlighter");
    MCommonLabelHighlighter *email = new MCommonLabelHighlighter(emailregexp);
    email->setObjectName("emailLabelHighlighter");
    MCommonLabelHighlighter *url = new MCommonLabelHighlighter(urlregexp);
    url->setObjectName("urlLabelHighlighter");

    connect(phone, SIGNAL(longPressed(QString)), this, SLOT(phoneNumberLongPressed(QString)));
    connect(phone, SIGNAL(clicked(QString)), this, SLOT(phoneNumberClicked(QString)));

    connect(email, SIGNAL(longPressed(QString)), this, SLOT(emailLongPressed(QString)));
    connect(email, SIGNAL(clicked(QString)), this, SLOT(emailClicked(QString)));

    connect(url, SIGNAL(longPressed(QString)), this, SLOT(urlLongPressed(QString)));
    connect(url, SIGNAL(clicked(QString)), this, SLOT(urlClicked(QString)));

    connect(ignoreClickAndLongPressCheckbox, SIGNAL(toggled(bool)), this, SLOT(enableOrDisableClickAndLongPressHandling(bool)));

    phoneHighlighter = phone;
    emailHighlighter = email;
    urlHighlighter = url;

    richLabel->addHighlighter(emailHighlighter);
    richLabel->addHighlighter(phoneHighlighter);
    richLabel->addHighlighter(urlHighlighter);

    retranslateUi();
}

void LabelPage::retranslateUi()
{
    //% "Labels"
    setTitle(qtTrId("xx_label_page_title"));
    if (!isContentCreated())
        return;
    //% "Simple Label is used mainly by other components, and it does "
    //% "not support any formatting or interaction.\n\n"
    //% "Rich Label supports multiple lines, HTML formatting and "
    //% "highlighting for links.\n\n"
    //% "All Labels can be aligned left, right or center and will be "
    //% "automatically truncated if the text does not fit inside "
    //% "the given area."
    infoLabel->setText("" + qtTrId("xx_label_page_info_label").replace('\n', "
"));
    //% "Simple Label"
    simpleLabel->setText(qtTrId("xx_simple_label"));
    //% "Rich Label bold, italic, "
    //% "http://www.nokia.com, +358401234567, fors.fagerstrom@email.com"
    richLabel->setText(qtTrId("xx_rich_label"));

    //% "Handle click and long press events:"
    ignoreClickAndLongPressLabel->setText(qtTrId("xx_label_page_handle_click_and_long_press_events"));

    update();
}

void LabelPage::phoneNumberLongPressed(const QString &link)
{
    mDebug("LabelPage::phoneNumberLongPressed()") << link;
}

void LabelPage::phoneNumberClicked(const QString &link)
{
    mDebug("LabelPage::phoneNumberClicked()") << link;
}

void LabelPage::emailLongPressed(const QString &link)
{
    mDebug("LabelPage::emailLongPressed()") << link;
}

void LabelPage::emailClicked(const QString &link)
{
    mDebug("LabelPage::emailClicked()") << link;
}

void LabelPage::urlLongPressed(const QString &link)
{
    mDebug("LabelPage::urlLongPressed()") << link;
}

void LabelPage::urlClicked(const QString &link)
{
    mDebug("LabelPage::urlClicked()") << link;
}

void LabelPage::enableOrDisableClickAndLongPressHandling(bool checked)
{
    phoneHighlighter->setIgnoreClickAndLongPressEvents(!checked);
    emailHighlighter->setIgnoreClickAndLongPressEvents(!checked);
    urlHighlighter->setIgnoreClickAndLongPressEvents(!checked);
}
<|endoftext|>


<commit_before>#include <type_traits>
#include "gtest/gtest.h"
#include "LockProxyProvider.hpp"

using But::Threading::LockProxyProvider;
using But::Threading::detail::LockProxy;

namespace
{

struct MyData: LockProxyProvider<MyData>
{
  void lock()   const { ++locks_; }
  void unlock() const { --locks_; }

  auto locks() const { return locks_; }
  void constFoo() const { }
  void nonConstFoo() { }

  mutable int locks_{0};
};

struct ButThreadingLockProxyProvider: public testing::Test
{
  MyData md_;
};

TEST_F(ButThreadingLockProxyProvider, ProxyLocksAndUnlocksObjectAutomatically)
{
  EXPECT_EQ( md_.locks_, 0 );
  {
    auto p = md_.withLock();
    (void)p;
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, ArrowOperatorOnProxyForwardsToActualClass)
{
  EXPECT_EQ(md_.locks_, 0u);
  const auto cnt = md_.withLock()->locks();
  EXPECT_EQ(cnt, 1u);
  EXPECT_EQ(md_.locks_, 0u);
}

TEST_F(ButThreadingLockProxyProvider, ArrowOperatorEnsureConstness)
{
  md_.withLock()->nonConstFoo();

  const auto& cmd = md_;
  cmd.withLock()->constFoo();
}

TEST_F(ButThreadingLockProxyProvider, ProxyIsMovable)
{
  EXPECT_TRUE( std::is_move_constructible<LockProxy<MyData>>::value );
  EXPECT_TRUE( std::is_move_assignable<LockProxy<MyData>>::value );
}

TEST_F(ButThreadingLockProxyProvider, MovingProxyDoesNotCauseExtraLockingNorUnlocking)
{
  EXPECT_TRUE( std::is_move_constructible<LockProxy<MyData>>::value );
  EXPECT_TRUE( std::is_move_assignable<LockProxy<MyData>>::value );

  EXPECT_EQ( md_.locks_, 0 );
  {
    auto p1 = md_.withLock();
    EXPECT_EQ( md_.locks_, 1 );
    auto p2 = std::move(p1);
    EXPECT_EQ( md_.locks_, 1 );
    p1 = std::move(p2);
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, MoveAsignmentReleasesPreviousLockWhenOwned)
{
  EXPECT_EQ( md_.locks_, 0 );
  MyData other;
  {
    auto p1 = other.withLock();
    auto p2 = md_.withLock();
    EXPECT_EQ( other.locks_, 1 );
    EXPECT_EQ( md_.locks_, 1 );
    p1 = std::move(p2);
    EXPECT_EQ( other.locks_, 0 );
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( other.locks_, 0 );
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, LockSelfAssignmentIsNoOp)
{
  EXPECT_EQ( md_.locks_, 0 );
  {
    auto p1 = md_.withLock();
    EXPECT_EQ( md_.locks_, 1 );
    auto&& p2 = std::move(p1);
    p1 = std::move(p2);
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, ProxyIsNonCopyable)
{
  EXPECT_FALSE( std::is_copy_constructible<LockProxy<MyData>>::value );
  EXPECT_FALSE( std::is_copy_assignable<LockProxy<MyData>>::value );
}

}
<commit_msg>fixed signed/unsigned mismatch<commit_after>#include <type_traits>
#include "gtest/gtest.h"
#include "LockProxyProvider.hpp"

using But::Threading::LockProxyProvider;
using But::Threading::detail::LockProxy;

namespace
{

struct MyData: LockProxyProvider<MyData>
{
  void lock()   const { ++locks_; }
  void unlock() const { --locks_; }

  auto locks() const { return locks_; }
  void constFoo() const { }
  void nonConstFoo() { }

  mutable int locks_{0};
};

struct ButThreadingLockProxyProvider: public testing::Test
{
  MyData md_;
};

TEST_F(ButThreadingLockProxyProvider, ProxyLocksAndUnlocksObjectAutomatically)
{
  EXPECT_EQ( md_.locks_, 0 );
  {
    auto p = md_.withLock();
    (void)p;
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, ArrowOperatorOnProxyForwardsToActualClass)
{
  EXPECT_EQ(md_.locks_, 0);
  const auto cnt = md_.withLock()->locks();
  EXPECT_EQ(cnt, 1);
  EXPECT_EQ(md_.locks_, 0);
}

TEST_F(ButThreadingLockProxyProvider, ArrowOperatorEnsureConstness)
{
  md_.withLock()->nonConstFoo();

  const auto& cmd = md_;
  cmd.withLock()->constFoo();
}

TEST_F(ButThreadingLockProxyProvider, ProxyIsMovable)
{
  EXPECT_TRUE( std::is_move_constructible<LockProxy<MyData>>::value );
  EXPECT_TRUE( std::is_move_assignable<LockProxy<MyData>>::value );
}

TEST_F(ButThreadingLockProxyProvider, MovingProxyDoesNotCauseExtraLockingNorUnlocking)
{
  EXPECT_TRUE( std::is_move_constructible<LockProxy<MyData>>::value );
  EXPECT_TRUE( std::is_move_assignable<LockProxy<MyData>>::value );

  EXPECT_EQ( md_.locks_, 0 );
  {
    auto p1 = md_.withLock();
    EXPECT_EQ( md_.locks_, 1 );
    auto p2 = std::move(p1);
    EXPECT_EQ( md_.locks_, 1 );
    p1 = std::move(p2);
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, MoveAsignmentReleasesPreviousLockWhenOwned)
{
  EXPECT_EQ( md_.locks_, 0 );
  MyData other;
  {
    auto p1 = other.withLock();
    auto p2 = md_.withLock();
    EXPECT_EQ( other.locks_, 1 );
    EXPECT_EQ( md_.locks_, 1 );
    p1 = std::move(p2);
    EXPECT_EQ( other.locks_, 0 );
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( other.locks_, 0 );
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, LockSelfAssignmentIsNoOp)
{
  EXPECT_EQ( md_.locks_, 0 );
  {
    auto p1 = md_.withLock();
    EXPECT_EQ( md_.locks_, 1 );
    auto&& p2 = std::move(p1);
    p1 = std::move(p2);
    EXPECT_EQ( md_.locks_, 1 );
  }
  EXPECT_EQ( md_.locks_, 0 );
}

TEST_F(ButThreadingLockProxyProvider, ProxyIsNonCopyable)
{
  EXPECT_FALSE( std::is_copy_constructible<LockProxy<MyData>>::value );
  EXPECT_FALSE( std::is_copy_assignable<LockProxy<MyData>>::value );
}

}
<|endoftext|>


<commit_before>/******************************************************************************

	File: VMRef.cpp

	Description:

	Interpreter methods to maintain VM reference table

******************************************************************************/

#include "Ist.h"
#include "Interprt.h"

// Smalltalk classes
#include "STArray.h"
#include "thrdcall.h"

///////////////////////////////////////////////////////////////////////////////
//
// Routines to provide generic support for references to objects from the VM
//
// The algorithm uses a linked list of free slots for adding a reference, but
// with a serial search on dereferencing. This would be better replaced with
// a hash table implementation using the identity hash of the object
TODO("Replace with hash table implementation")

Oop* Interpreter::m_pVMRefs = 0;
int Interpreter::m_nMaxVMRefs = 0;
int	Interpreter::m_nFreeVMRef = -1;

// Add a reference to an object in use by the VM by storing it in an array reserved
// for the purpose, which is itself reference from the special VMPointers root object
void Interpreter::AddVMReference(Oop object)
{
	if (!ObjectMemoryIsIntegerObject(object))
		AddVMReference((OTE*)object);
}

// Add a reference to an object in use by the VM by storing it in an array reserved
// for the purpose, which is itself reference from the special VMPointers root object
void Interpreter::AddVMReference(OTE* pOTE)
{
	// Don't store ref's to objects which don't need ref. counting
	if (!ObjectMemory::isPermanent(pOTE))
	{
		if (m_nFreeVMRef >= m_nMaxVMRefs)
		{
			// Need to grow the array
			m_nFreeVMRef = m_nMaxVMRefs;
			m_nMaxVMRefs += VMREFSGROWTH;
			m_pVMRefs = ((Array*)ObjectMemory::resize((PointersOTE*)Pointers.VMReferences, m_nMaxVMRefs, false))->m_elements;
			for (int i=m_nFreeVMRef;i<m_nMaxVMRefs;i++)
				m_pVMRefs[i] = ObjectMemoryIntegerObjectOf(i+1);
		}
		const int empty = m_nFreeVMRef;
		const Oop oopNextEmpty = m_pVMRefs[empty];
		HARDASSERT(ObjectMemoryIsIntegerObject(oopNextEmpty));
		m_nFreeVMRef = (int)ObjectMemoryIntegerValueOf(oopNextEmpty);
		m_pVMRefs[empty] = Oop(pOTE);
		pOTE->countUp();
	}
	//CHECKREFERENCES
}

// Remove ref. to previously registered object.
// N.B. Assumes that
void Interpreter::RemoveVMReference(Oop object)
{
	if (!ObjectMemoryIsIntegerObject(object))
		RemoveVMReference((OTE*)object);
}

// Remove ref. to previously registered object.
// N.B. Assumes that
void Interpreter::RemoveVMReference(OTE* pOTE)
{
	if (!ObjectMemory::isPermanent(pOTE))
	{
		for (int i=0;i<m_nMaxVMRefs;i++)
		{
			if (m_pVMRefs[i] == Oop(pOTE))
			{
				ASSERT(!ObjectMemoryIsIntegerObject(m_pVMRefs[i]));

				// Link onto the front of the free list
				m_pVMRefs[i] = ObjectMemoryIntegerObjectOf(m_nFreeVMRef);
				m_nFreeVMRef = i;

				break;
			}
		}
		pOTE->countDown();
	}
	//CHECKREFERENCES
}

///////////////////////////////////////////////////////////////////////////////
//

#ifdef _DEBUG
	//========================
	//ReincrementVMReferences
	//========================
	// ObjectMemory::checkReferences(), in DEBUG version, clears then re-increments the reference counts of all
	// accessible objects. This function is called to re-increment the reference count of the objects to which
	// the VM holds a strong reference
	//
	void Interpreter::ReincrementVMReferences()
	{
		// VM holds onto an array into which it stores objects which it is
		// currently referencing from outside the Smalltalk world, this array
		// is one of the root objects used for garbage collection, but its own
		// count must be artificially maintained during a check references
		// this is achieved through the overflow of the counts of all objects
		// in the global pointers structure (see below)

		m_oteNewProcess->countUp();					// new process or nil
		m_oteTimerSem->beSticky();					// Timer Semaphore or nil
		m_oteUnderConstruction->countUp();			// Window currently under construction or nil

		OverlappedCall::ReincrementProcessReferences();

		//m_oopMessageSelector = Pointers.Nil;
		//m_oopNewMethod = Pointers.Nil;

		ObjectMemory::addVMRefs();
	}
#endif
<commit_msg>With this commit the Release configuration should build without errors.<commit_after>/******************************************************************************

	File: VMRef.cpp

	Description:

	Interpreter methods to maintain VM reference table

******************************************************************************/

#include "Ist.h"
#include "Interprt.h"

// Smalltalk classes
#include "STArray.h"
#include "thrdcall.h"

///////////////////////////////////////////////////////////////////////////////
//
// Routines to provide generic support for references to objects from the VM
//
// The algorithm uses a linked list of free slots for adding a reference, but
// with a serial search on dereferencing. This would be better replaced with
// a hash table implementation using the identity hash of the object
TODO("Replace with hash table implementation")

#ifdef _DEBUG		// JGFoster

Oop* Interpreter::m_pVMRefs = 0;
int Interpreter::m_nMaxVMRefs = 0;
int	Interpreter::m_nFreeVMRef = -1;

// Add a reference to an object in use by the VM by storing it in an array reserved
// for the purpose, which is itself reference from the special VMPointers root object
void Interpreter::AddVMReference(Oop object)
{
	if (!ObjectMemoryIsIntegerObject(object))
		AddVMReference((OTE*)object);
}

// Add a reference to an object in use by the VM by storing it in an array reserved
// for the purpose, which is itself reference from the special VMPointers root object
void Interpreter::AddVMReference(OTE* pOTE)
{
	// Don't store ref's to objects which don't need ref. counting
	if (!ObjectMemory::isPermanent(pOTE))
	{
		if (m_nFreeVMRef >= m_nMaxVMRefs)
		{
			// Need to grow the array
			m_nFreeVMRef = m_nMaxVMRefs;
			m_nMaxVMRefs += VMREFSGROWTH;
			m_pVMRefs = ((Array*)ObjectMemory::resize((PointersOTE*)Pointers.VMReferences, m_nMaxVMRefs, false))->m_elements;
			for (int i=m_nFreeVMRef;i<m_nMaxVMRefs;i++)
				m_pVMRefs[i] = ObjectMemoryIntegerObjectOf(i+1);
		}
		const int empty = m_nFreeVMRef;
		const Oop oopNextEmpty = m_pVMRefs[empty];
		HARDASSERT(ObjectMemoryIsIntegerObject(oopNextEmpty));
		m_nFreeVMRef = (int)ObjectMemoryIntegerValueOf(oopNextEmpty);
		m_pVMRefs[empty] = Oop(pOTE);
		pOTE->countUp();
	}
	//CHECKREFERENCES
}

// Remove ref. to previously registered object.
// N.B. Assumes that
void Interpreter::RemoveVMReference(Oop object)
{
	if (!ObjectMemoryIsIntegerObject(object))
		RemoveVMReference((OTE*)object);
}

// Remove ref. to previously registered object.
// N.B. Assumes that
void Interpreter::RemoveVMReference(OTE* pOTE)
{
	if (!ObjectMemory::isPermanent(pOTE))
	{
		for (int i=0;i<m_nMaxVMRefs;i++)
		{
			if (m_pVMRefs[i] == Oop(pOTE))
			{
				ASSERT(!ObjectMemoryIsIntegerObject(m_pVMRefs[i]));

				// Link onto the front of the free list
				m_pVMRefs[i] = ObjectMemoryIntegerObjectOf(m_nFreeVMRef);
				m_nFreeVMRef = i;

				break;
			}
		}
		pOTE->countDown();
	}
	//CHECKREFERENCES
}

///////////////////////////////////////////////////////////////////////////////
//

//	#ifdef _DEBUG		// JGFoster
	//========================
	//ReincrementVMReferences
	//========================
	// ObjectMemory::checkReferences(), in DEBUG version, clears then re-increments the reference counts of all
	// accessible objects. This function is called to re-increment the reference count of the objects to which
	// the VM holds a strong reference
	//
	void Interpreter::ReincrementVMReferences()
	{
		// VM holds onto an array into which it stores objects which it is
		// currently referencing from outside the Smalltalk world, this array
		// is one of the root objects used for garbage collection, but its own
		// count must be artificially maintained during a check references
		// this is achieved through the overflow of the counts of all objects
		// in the global pointers structure (see below)

		m_oteNewProcess->countUp();					// new process or nil
		m_oteTimerSem->beSticky();					// Timer Semaphore or nil
		m_oteUnderConstruction->countUp();			// Window currently under construction or nil

		OverlappedCall::ReincrementProcessReferences();

		//m_oopMessageSelector = Pointers.Nil;
		//m_oopNewMethod = Pointers.Nil;

		ObjectMemory::addVMRefs();
	}
#endif
<|endoftext|>


<commit_before>// FRAGMENT(defintions)
#define SEQAN_PROFILE // enable time measurements

#include <iostream>
#include <seqan/basic.h>

using namespace seqan;

int main()
{
	Allocator<MultiPool< > > mpa;
	Allocator<SimpleAlloc< > > sa;
	unsigned runs = 100000;
	char *buf;
// FRAGMENT(time-measurements)
	// block size 10
	unsigned bs[3];
	bs[0] = 10;
	bs[1] = 100;
	bs[2] = 1000;
	SEQAN_PROTIMESTART(timeAlloc);

	// loop through the different block sizes
	for (int i=0; i<3; ++i) {
		for (int j=0; j<runs; ++j) {
			allocate(mpa,buf,bs[i],TagAllocateTemp());
		}
		clear(mpa);
		std::cout << "Allocating " << runs << " times blocks of size "
					<< bs[i] << " with MultiPool Allocator took " << SEQAN_PROTIMEDIFF(timeAlloc) << std::endl;
	// the PROTIMEDIFF macro sets the internal timer clock to zero
		for (int j=0; j<runs; ++j) {
			allocate(sa,buf,bs[i],TagAllocateTemp());
		}
		clear(sa);
		std::cout << "Allocating " << runs << " times blocks of size "
		<< bs[i] << " with Standard Allocator took " << SEQAN_PROTIMEDIFF(timeAlloc) << std::endl;
	}

	return 0;
}

<commit_msg><commit_after>// FRAGMENT(definitions)
#define SEQAN_PROFILE // enable time measurements

#include <iostream>
#include <seqan/basic.h>

using namespace seqan;

int main()
{
	Allocator<MultiPool< > > mpa;
	Allocator<SimpleAlloc< > > sa;
	unsigned runs = 100000;
	char *buf;
// FRAGMENT(time-measurements)
	// block size 10
	unsigned bs[3];
	bs[0] = 10;
	bs[1] = 100;
	bs[2] = 1000;
	SEQAN_PROTIMESTART(timeAlloc);

	// loop through the different block sizes
	for (int i=0; i<3; ++i) {
		for (int j=0; j<runs; ++j) {
			allocate(mpa,buf,bs[i],TagAllocateTemp());
		}
		clear(mpa);
		std::cout << "Allocating " << runs << " times blocks of size "
					<< bs[i] << " with MultiPool Allocator took " << SEQAN_PROTIMEDIFF(timeAlloc) << std::endl;
	// the PROTIMEDIFF macro sets the internal timer clock to zero
		for (int j=0; j<runs; ++j) {
			allocate(sa,buf,bs[i],TagAllocateTemp());
		}
		clear(sa);
		std::cout << "Allocating " << runs << " times blocks of size "
		<< bs[i] << " with Standard Allocator took " << SEQAN_PROTIMEDIFF(timeAlloc) << std::endl;
	}

	return 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pages.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-10-12 14:13:22 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _PAGES_HXX_
#define _PAGES_HXX_

#include <vcl/tabpage.hxx>
#include <vcl/fixed.hxx>
#include <vcl/button.hxx>
#include <vcl/dialog.hxx>
#include <vcl/scrbar.hxx>
#include <svtools/wizardmachine.hxx>
#include <svtools/svmedit.hxx>
#include <svtools/lstner.hxx>
#include <svtools/xtextedt.hxx>

namespace desktop
{
class WelcomePage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    svt::OWizardMachine *m_pParent;
    enum OEMType
    {
        OEM_NONE, OEM_NORMAL, OEM_EXTENDED
    };
    OEMType checkOEM();
    bool bIsEvalVersion;
    bool bNoEvalText;
    void checkEval();

public:
    WelcomePage( svt::OWizardMachine* parent, const ResId& resid);
protected:
    virtual void ActivatePage();
};

class LicenseView : public MultiLineEdit, public SfxListener
{
    BOOL            mbEndReached;
    Link            maEndReachedHdl;
    Link            maScrolledHdl;

public:
    LicenseView( Window* pParent, const ResId& rResId );
    ~LicenseView();

    void ScrollDown( ScrollType eScroll );

    BOOL IsEndReached() const;
    BOOL EndReached() const { return mbEndReached; }
    void SetEndReached( BOOL bEnd ) { mbEndReached = bEnd; }

    void SetEndReachedHdl( const Link& rHdl )  { maEndReachedHdl = rHdl; }
    const Link& GetAutocompleteHdl() const { return maEndReachedHdl; }

    void SetScrolledHdl( const Link& rHdl )  { maScrolledHdl = rHdl; }
    const Link& GetScrolledHdl() const { return maScrolledHdl; }

    virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

protected:
    using MultiLineEdit::Notify;
};

class LicensePage : public svt::OWizardPage
{
private:
    svt::OWizardMachine *m_pParent;
    FixedText m_ftHead;
    FixedText m_ftBody1;
    FixedText m_ftBody1Txt;
    FixedText m_ftBody2;
    FixedText m_ftBody2Txt;
    LicenseView m_mlLicense;
    PushButton m_pbDown;
    sal_Bool m_bLicenseRead;
public:
    LicensePage( svt::OWizardMachine* parent, const ResId& resid);
private:
    DECL_LINK(PageDownHdl, PushButton*);
    DECL_LINK(EndReachedHdl, LicenseView*);
    DECL_LINK(ScrolledHdl, LicenseView*);
protected:
    virtual sal_Bool determineNextButtonState();
    virtual void ActivatePage();
};

class MigrationPage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    CheckBox m_cbMigration;
    sal_Bool m_bMigrationDone;
public:
    MigrationPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);

protected:
    virtual void ActivatePage();
};

class UserPage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    FixedText m_ftFirst;
    Edit m_edFirst;
    FixedText m_ftLast;
    Edit m_edLast;
    FixedText m_ftInitials;
    Edit m_edInitials;
    FixedText m_ftFather;
    Edit m_edFather;
    LanguageType m_lang;

public:
    UserPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);
protected:
    virtual void ActivatePage();
};

class UpdateCheckPage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    CheckBox m_cbUpdateCheck;
public:
    UpdateCheckPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);

protected:
    virtual void ActivatePage();
};

class RegistrationPage : public svt::OWizardPage
{
private:
    FixedText m_ftHeader;
    FixedText m_ftBody;
    FixedImage m_fiImage;
    RadioButton m_rbNow;
    RadioButton m_rbLater;
    RadioButton m_rbNever;
    RadioButton m_rbReg;
    FixedLine m_flSeparator;
    FixedText m_ftEnd;
    sal_Bool    m_bNeverVisible;

    void updateButtonStates();
    void impl_retrieveConfigurationData();

public:
    RegistrationPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);
protected:
    virtual sal_Bool determineNextButtonState();
    virtual void ActivatePage();
};

}
#endif
<commit_msg>INTEGRATION: CWS fwk82_SRC680 (1.9.302); FILE MERGED 2008/01/09 08:28:54 as 1.9.302.1: #i84169# optimize startup wizard<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pages.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2008-01-29 16:30:51 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _PAGES_HXX_
#define _PAGES_HXX_

#include <vcl/tabpage.hxx>
#include <vcl/fixed.hxx>
#include <vcl/button.hxx>
#include <vcl/dialog.hxx>
#include <vcl/scrbar.hxx>
#include <svtools/wizardmachine.hxx>
#include <svtools/svmedit.hxx>
#include <svtools/lstner.hxx>
#include <svtools/xtextedt.hxx>

namespace desktop
{
class WelcomePage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    svt::OWizardMachine *m_pParent;
    sal_Bool m_bLicenseNeedsAcceptance;
    enum OEMType
    {
        OEM_NONE, OEM_NORMAL, OEM_EXTENDED
    };
    OEMType checkOEM();
    bool bIsEvalVersion;
    bool bNoEvalText;
    void checkEval();

public:
    WelcomePage( svt::OWizardMachine* parent, const ResId& resid, sal_Bool bLicenseNeedsAcceptance );
protected:
    virtual void ActivatePage();
};

class LicenseView : public MultiLineEdit, public SfxListener
{
    BOOL            mbEndReached;
    Link            maEndReachedHdl;
    Link            maScrolledHdl;

public:
    LicenseView( Window* pParent, const ResId& rResId );
    ~LicenseView();

    void ScrollDown( ScrollType eScroll );

    BOOL IsEndReached() const;
    BOOL EndReached() const { return mbEndReached; }
    void SetEndReached( BOOL bEnd ) { mbEndReached = bEnd; }

    void SetEndReachedHdl( const Link& rHdl )  { maEndReachedHdl = rHdl; }
    const Link& GetAutocompleteHdl() const { return maEndReachedHdl; }

    void SetScrolledHdl( const Link& rHdl )  { maScrolledHdl = rHdl; }
    const Link& GetScrolledHdl() const { return maScrolledHdl; }

    virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

protected:
    using MultiLineEdit::Notify;
};

class LicensePage : public svt::OWizardPage
{
private:
    svt::OWizardMachine *m_pParent;
    FixedText m_ftHead;
    FixedText m_ftBody1;
    FixedText m_ftBody1Txt;
    FixedText m_ftBody2;
    FixedText m_ftBody2Txt;
    LicenseView m_mlLicense;
    PushButton m_pbDown;
    sal_Bool m_bLicenseRead;
public:
    LicensePage( svt::OWizardMachine* parent, const ResId& resid, const rtl::OUString &rLicensePath );
private:
    DECL_LINK(PageDownHdl, PushButton*);
    DECL_LINK(EndReachedHdl, LicenseView*);
    DECL_LINK(ScrolledHdl, LicenseView*);
protected:
    virtual sal_Bool determineNextButtonState();
    virtual void ActivatePage();
};

class MigrationPage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    CheckBox m_cbMigration;
    sal_Bool m_bMigrationDone;
public:
    MigrationPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);

protected:
    virtual void ActivatePage();
};

class UserPage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    FixedText m_ftFirst;
    Edit m_edFirst;
    FixedText m_ftLast;
    Edit m_edLast;
    FixedText m_ftInitials;
    Edit m_edInitials;
    FixedText m_ftFather;
    Edit m_edFather;
    LanguageType m_lang;

public:
    UserPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);
protected:
    virtual void ActivatePage();
};

class UpdateCheckPage : public svt::OWizardPage
{
private:
    FixedText m_ftHead;
    FixedText m_ftBody;
    CheckBox m_cbUpdateCheck;
public:
    UpdateCheckPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);

protected:
    virtual void ActivatePage();
};

class RegistrationPage : public svt::OWizardPage
{
private:
    FixedText m_ftHeader;
    FixedText m_ftBody;
    FixedImage m_fiImage;
    RadioButton m_rbNow;
    RadioButton m_rbLater;
    RadioButton m_rbNever;
    RadioButton m_rbReg;
    FixedLine m_flSeparator;
    FixedText m_ftEnd;
    sal_Bool    m_bNeverVisible;

    void updateButtonStates();
    void impl_retrieveConfigurationData();

public:
    RegistrationPage( svt::OWizardMachine* parent, const ResId& resid);
    virtual sal_Bool commitPage(COMMIT_REASON _eReason);
protected:
    virtual sal_Bool determineNextButtonState();
    virtual void ActivatePage();
};

}
#endif
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CommonData.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "CommonData.h"
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#include "Exceptions.h"
using namespace std;
using namespace dev;

std::string dev::escaped(std::string const& _s, bool _all)
{
	static const map<char, char> prettyEscapes{{'\r', 'r'}, {'\n', 'n'}, {'\t', 't'}, {'\v', 'v'}};
	std::string ret;
	ret.reserve(_s.size() + 2);
	ret.push_back('"');
	for (auto i: _s)
		if (i == '"' && !_all)
			ret += "\\\"";
		else if (i == '\\' && !_all)
			ret += "\\\\";
		else if (prettyEscapes.count(i) && !_all)
		{
			ret += '\\';
			ret += prettyEscapes.find(i)->second;
		}
		else if (i < ' ' || _all)
		{
			ret += "\\x";
			ret.push_back("0123456789abcdef"[(uint8_t)i / 16]);
			ret.push_back("0123456789abcdef"[(uint8_t)i % 16]);
		}
		else
			ret.push_back(i);
	ret.push_back('"');
	return ret;
}

int dev::fromHex(char _i, WhenError _throw)
{
	if (_i >= '0' && _i <= '9')
		return _i - '0';
	if (_i >= 'a' && _i <= 'f')
		return _i - 'a' + 10;
	if (_i >= 'A' && _i <= 'F')
		return _i - 'A' + 10;
	if (_throw == WhenError::Throw)
		BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
	else
		return -1;
}

bytes dev::fromHex(std::string const& _s, WhenError _throw)
{
	unsigned s = (_s.size() >= 2 && _s[0] == '0' && _s[1] == 'x') ? 2 : 0;
	std::vector<uint8_t> ret;
	ret.reserve((_s.size() - s + 1) / 2);

	if (_s.size() % 2)
	{
		int h = fromHex(_s[s++], WhenError::DontThrow);
		if (h != -1)
			ret.push_back(h);
		else if (_throw == WhenError::Throw)
			BOOST_THROW_EXCEPTION(BadHexCharacter());
		else
			return bytes();
	}
	for (unsigned i = s; i < _s.size(); i += 2)
	{
		int h = fromHex(_s[i], WhenError::DontThrow);
		int l = fromHex(_s[i + 1], WhenError::DontThrow);
		if (h != -1 && l != -1)
			ret.push_back((byte)(h * 16 + l));
		else if (_throw == WhenError::Throw)
			BOOST_THROW_EXCEPTION(BadHexCharacter());
		else
			return bytes();
	}
	return ret;
}
<commit_msg>Windows build fix.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CommonData.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "CommonData.h"
#include "Exceptions.h"
using namespace std;
using namespace dev;

std::string dev::escaped(std::string const& _s, bool _all)
{
	static const map<char, char> prettyEscapes{{'\r', 'r'}, {'\n', 'n'}, {'\t', 't'}, {'\v', 'v'}};
	std::string ret;
	ret.reserve(_s.size() + 2);
	ret.push_back('"');
	for (auto i: _s)
		if (i == '"' && !_all)
			ret += "\\\"";
		else if (i == '\\' && !_all)
			ret += "\\\\";
		else if (prettyEscapes.count(i) && !_all)
		{
			ret += '\\';
			ret += prettyEscapes.find(i)->second;
		}
		else if (i < ' ' || _all)
		{
			ret += "\\x";
			ret.push_back("0123456789abcdef"[(uint8_t)i / 16]);
			ret.push_back("0123456789abcdef"[(uint8_t)i % 16]);
		}
		else
			ret.push_back(i);
	ret.push_back('"');
	return ret;
}

int dev::fromHex(char _i, WhenError _throw)
{
	if (_i >= '0' && _i <= '9')
		return _i - '0';
	if (_i >= 'a' && _i <= 'f')
		return _i - 'a' + 10;
	if (_i >= 'A' && _i <= 'F')
		return _i - 'A' + 10;
	if (_throw == WhenError::Throw)
		BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
	else
		return -1;
}

bytes dev::fromHex(std::string const& _s, WhenError _throw)
{
	unsigned s = (_s.size() >= 2 && _s[0] == '0' && _s[1] == 'x') ? 2 : 0;
	std::vector<uint8_t> ret;
	ret.reserve((_s.size() - s + 1) / 2);

	if (_s.size() % 2)
	{
		int h = fromHex(_s[s++], WhenError::DontThrow);
		if (h != -1)
			ret.push_back(h);
		else if (_throw == WhenError::Throw)
			BOOST_THROW_EXCEPTION(BadHexCharacter());
		else
			return bytes();
	}
	for (unsigned i = s; i < _s.size(); i += 2)
	{
		int h = fromHex(_s[i], WhenError::DontThrow);
		int l = fromHex(_s[i + 1], WhenError::DontThrow);
		if (h != -1 && l != -1)
			ret.push_back((byte)(h * 16 + l));
		else if (_throw == WhenError::Throw)
			BOOST_THROW_EXCEPTION(BadHexCharacter());
		else
			return bytes();
	}
	return ret;
}
<|endoftext|>


<commit_before>//---
//
// License: MIT
//
// File: ossim-foo.cpp
//
// Description: Contains application definition "ossim-foo" app.
//
// NOTE:  This is supplied for simple quick test. DO NOT checkin your test to
//        the svn repository.  Simply edit ossim-foo.cpp and run your test.
//        After completion you can do a "git checkout -- ossimfoo.cpp" if
//        you want to keep your working repository up to snuff.
//
// $Id$
//---

// System includes:
#include <cmath>
#include <memory>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstring>

// Put your includes here:
#include <ossim/init/ossimInit.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimCommon.h>
#include <ossim/imaging/ossimImageFactoryRegistry.h>
#include <ossim/imaging/ossimImageGoemetry.h>
#include <ossim/imaging/ossimImageHandler.h>
#include <ossim/base/ossimArgumentParser.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>

using namespace std;

int main(int argc, char *argv[])
{
   try
   {
      /* code */
   }
   catch(const std::exception& e)
   {
      std::cerr << e.what() << '\n';
   }

   return 0;
}
<commit_msg>Added argument parser back in<commit_after>//---
//
// License: MIT
//
// File: ossim-foo.cpp
//
// Description: Contains application definition "ossim-foo" app.
//
// NOTE:  This is supplied for simple quick test. DO NOT checkin your test to
//        the svn repository.  Simply edit ossim-foo.cpp and run your test.
//        After completion you can do a "git checkout -- ossimfoo.cpp" if
//        you want to keep your working repository up to snuff.
//
// $Id$
//---

// System includes:
#include <cmath>
#include <memory>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstring>

// Put your includes here:
#include <ossim/init/ossimInit.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimCommon.h>
#include <ossim/imaging/ossimImageFactoryRegistry.h>
#include <ossim/imaging/ossimImageGoemetry.h>
#include <ossim/imaging/ossimImageHandler.h>
#include <ossim/base/ossimArgumentParser.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
#include <ossim/base/ossimTimer.h>

using namespace std;

int main(int argc, char *argv[])
{
   ossimTimer timer;
   // Start the timer.
   ossimTimer::Timer_t tickStart = timer.tick();
   ossimArgumentParser ap(&argc, argv);

   // Initialize ossim stuff, factories, plugin, etc.
   ossimInit::instance()->initialize(ap);
   try
   {
      /* code */
   }
   catch(const std::exception& e)
   {
      ossimNotify(ossimNotifyLevel_WARN) << e.what() << std::endl;
      exit(1);
   }
   ossimTimer::Timer_t tickEnd = timer.tick();

   ossimNotify(ossimNotifyLevel_NOTICE)
       << "elapsed time in seconds: "
       << std::setiosflags(ios::fixed)
       << std::setprecision(3)
       << timer.delta_s(tickStart, tickEnd) << endl;

   return 0;
}
<|endoftext|>