--- /dev/null 2018-04-03 12:55:20.301839954 +0200 +++ new/src/hotspot/share/gc/z/zMessagePort.inline.hpp 2018-06-08 19:46:21.874793481 +0200 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZMESSAGEPORT_INLINE_HPP +#define SHARE_GC_Z_ZMESSAGEPORT_INLINE_HPP + +#include "gc/z/zMessagePort.hpp" +#include "gc/z/zFuture.inline.hpp" +#include "gc/z/zList.inline.hpp" +#include "runtime/mutexLocker.hpp" + +template +class ZMessageRequest : public StackObj { + friend class ZList; + +private: + T _message; + uint64_t _seqnum; + ZFuture _result; + ZListNode _node; + +public: + void initialize(T message, uint64_t seqnum) { + _message = message; + _seqnum = seqnum; + } + + T message() const { + return _message; + } + + uint64_t seqnum() const { + return _seqnum; + } + + void wait() { + const T message = _result.get(); + assert(message == _message, "Message mismatch"); + } + + void satisfy(T message) { + _result.set(message); + } +}; + +template +inline ZMessagePort::ZMessagePort() : + _monitor(Monitor::leaf, + "ZMessagePort", + Monitor::_allow_vm_block_flag, + Monitor::_safepoint_check_never), + _has_message(false), + _seqnum(0), + _queue() {} + +template +inline void ZMessagePort::send_sync(T message) { + Request request; + + { + // Enqueue message + MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag); + request.initialize(message, _seqnum); + _queue.insert_last(&request); + ml.notify(); + } + + // Wait for completion + request.wait(); +} + +template +inline void ZMessagePort::send_async(T message) { + MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag); + if (!_has_message) { + // Post message + _message = message; + _has_message = true; + ml.notify(); + } +} + +template +inline T ZMessagePort::receive() { + MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag); + + // Wait for message + while (!_has_message && _queue.is_empty()) { + ml.wait(Monitor::_no_safepoint_check_flag); + } + + // Increment request sequence number + _seqnum++; + + if (!_has_message) { + // Message available in the queue + _message = _queue.first()->message(); + _has_message = true; + } + + return _message; +} + +template +inline void ZMessagePort::ack() { + MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag); + + if (!_has_message) { + // Nothing to ack + return; + } + + // Satisfy requests (and duplicates) in queue + ZListIterator iter(&_queue); + for (Request* request; iter.next(&request);) { + if (request->message() == _message && request->seqnum() < _seqnum) { + // Dequeue and satisfy request. Note that the dequeue operation must + // happen first, since the request will immediately be deallocated + // once it has been satisfied. + _queue.remove(request); + request->satisfy(_message); + } + } + + if (_queue.is_empty()) { + // Queue is empty + _has_message = false; + } else { + // Post first message in queue + _message = _queue.first()->message(); + } +} + +inline void ZRendezvousPort::signal() { + _port.send_sync(true /* ignored */); +} + +inline void ZRendezvousPort::wait() { + _port.receive(); +} + +inline void ZRendezvousPort::ack() { + _port.ack(); +} + +#endif // SHARE_GC_Z_ZMESSAGEPORT_INLINE_HPP