13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Test Executor
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Cross-thread function call dispatcher.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xeCallQueue.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline int getNextQueueSize (int curSize, int minNewSize)
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::max(curSize*2, 1<<deLog2Ceil32(minNewSize));
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace xe
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CallQueue
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCallQueue::CallQueue (void)
415717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi	: m_canceled	(false)
425717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi	, m_callSem		(0)
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_callQueue	(64)
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCallQueue::~CallQueue (void)
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Destroy all calls.
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<Call*>::iterator i = m_calls.begin(); i != m_calls.end(); i++)
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
545717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvivoid CallQueue::cancel (void)
555717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi{
565717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi	m_canceled = true;
575717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi	m_callSem.increment();
585717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi}
595717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CallQueue::callNext (void)
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Call* call = DE_NULL;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Wait for a call.
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_callSem.decrement();
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
675717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi	if (m_canceled)
685717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi		return;
695717785063a5db999d8f5a1cc067eba5fcc7409aMika Isojärvi
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Acquire call from buffer.
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::ScopedLock lock(m_lock);
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		call = m_callQueue.popBack();
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Enqueue lock is not held during call so it is possible to enqueue more work from dispatched call.
791592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry		CallReader reader(call);
801592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry
811592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry		call->getFunction()(reader);
821592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry
831592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry		// check callee consumed all
841592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry		DE_ASSERT(reader.isDataConsumed());
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		call->clear();
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception&)
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		try
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try to push call into free calls list.
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			de::ScopedLock lock(m_lock);
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_freeCalls.push_back(call);
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		catch (const std::exception&)
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// We can't do anything but ignore this.
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Push back to free calls list.
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::ScopedLock lock(m_lock);
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_freeCalls.push_back(call);
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCall* CallQueue::getEmptyCall (void)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::ScopedLock	lock	(m_lock);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Call*			call	= DE_NULL;
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Try to get from free calls list.
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_freeCalls.empty())
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		call = m_freeCalls.back();
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_freeCalls.pop_back();
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// If no free calls were available, create a new.
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!call)
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_calls.reserve(m_calls.size()+1);
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		call = new Call();
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_calls.push_back(call);
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return call;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CallQueue::enqueue (Call* call)
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::ScopedLock lock(m_lock);
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_callQueue.getNumFree() == 0)
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Call queue must be grown.
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_callQueue.resize(getNextQueueSize(m_callQueue.getSize(), m_callQueue.getSize()+1));
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_callQueue.pushFront(call);
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_callSem.increment();
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CallQueue::freeCall (Call* call)
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::ScopedLock lock(m_lock);
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_freeCalls.push_back(call);
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Call
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCall::Call (void)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_func(DE_NULL)
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCall::~Call (void)
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Call::clear (void)
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_func = DE_NULL;
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_data.clear();
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CallReader
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1723c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCallReader::CallReader (Call* call)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_call	(call)
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_curPos	(0)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
178745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyryvoid CallReader::read (deUint8* bytes, size_t numBytes)
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize());
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemcpy(bytes, m_call->getData()+m_curPos, numBytes);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_curPos += numBytes;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
185745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyryconst deUint8* CallReader::getDataBlock (size_t numBytes)
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize());
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8* ptr = m_call->getData()+m_curPos;
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_curPos += numBytes;
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ptr;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1951592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyrybool CallReader::isDataConsumed (void) const
1961592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry{
1971592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry	return m_curPos == m_call->getDataSize();
1981592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry}
1991592f16d1fc9edde443474e1835746f705ed79a9Jarkko Pöyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCallReader& operator>> (CallReader& reader, std::string& value)
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	value.clear();
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		char c;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		reader.read((deUint8*)&c, sizeof(char));
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (c != 0)
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			value.push_back(c);
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return reader;
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CallWriter
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2183c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCallWriter::CallWriter (CallQueue* queue, Call::Function function)
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_queue		(queue)
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_call		(queue->getEmptyCall())
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_enqueued	(false)
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_call->setFunction(function);
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2263c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCallWriter::~CallWriter (void)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_enqueued)
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_queue->freeCall(m_call);
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
232745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyryvoid CallWriter::write (const deUint8* bytes, size_t numBytes)
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_enqueued);
235745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry	size_t curPos = m_call->getDataSize();
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_call->setDataSize(curPos+numBytes);
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemcpy(m_call->getData()+curPos, bytes, numBytes);
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CallWriter::enqueue (void)
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_enqueued);
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_queue->enqueue(m_call);
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_enqueued = true;
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCallWriter& operator<< (CallWriter& writer, const char* str)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int pos = 0;
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writer.write((const deUint8*)str + pos, sizeof(char));
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (str[pos] == 0)
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos += 1;
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return writer;
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // xe
262