Mercurial > hg > CbC > CbC_llvm
view flang/runtime/unit-map.h @ 266:00f31e85ec16 default tip
Added tag current for changeset 31d058e83c98
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 14 Oct 2023 10:13:55 +0900 |
parents | c4bab56944e8 |
children |
line wrap: on
line source
//===-- runtime/unit-map.h --------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Maps Fortran unit numbers to their ExternalFileUnit instances. // A simple hash table with forward-linked chains per bucket. #ifndef FORTRAN_RUNTIME_UNIT_MAP_H_ #define FORTRAN_RUNTIME_UNIT_MAP_H_ #include "lock.h" #include "unit.h" #include "flang/Common/fast-int-set.h" #include "flang/Runtime/memory.h" #include <cstdint> #include <cstdlib> namespace Fortran::runtime::io { class UnitMap { public: ExternalFileUnit *LookUp(int n) { CriticalSection critical{lock_}; return Find(n); } ExternalFileUnit *LookUpOrCreate( int n, const Terminator &terminator, bool &wasExtant) { CriticalSection critical{lock_}; if (auto *p{Find(n)}) { wasExtant = true; return p; } else { wasExtant = false; return n >= 0 ? &Create(n, terminator) : nullptr; } } // Unit look-up by name is needed for INQUIRE(FILE="...") ExternalFileUnit *LookUp(const char *path, std::size_t pathLen) { CriticalSection critical{lock_}; return Find(path, pathLen); } ExternalFileUnit &NewUnit(const Terminator &); // To prevent races, the unit is removed from the map if it exists, // and put on the closing_ list until DestroyClosed() is called. ExternalFileUnit *LookUpForClose(int); void DestroyClosed(ExternalFileUnit &); void CloseAll(IoErrorHandler &); void FlushAll(IoErrorHandler &); private: struct Chain { explicit Chain(int n) : unit{n} {} ExternalFileUnit unit; OwningPtr<Chain> next{nullptr}; }; static constexpr int buckets_{1031}; // must be prime // The pool of recyclable new unit numbers uses the range that // works even with INTEGER(kind=1). 0 and -1 are never used. static constexpr int maxNewUnits_{129}; // [ -128 .. 0 ] int Hash(int n) { return std::abs(n) % buckets_; } void Initialize(); ExternalFileUnit *Find(int n) { Chain *previous{nullptr}; int hash{Hash(n)}; for (Chain *p{bucket_[hash].get()}; p; previous = p, p = p->next.get()) { if (p->unit.unitNumber() == n) { if (previous) { // Move found unit to front of chain for quicker lookup next time previous->next.swap(p->next); // now p->next.get() == p bucket_[hash].swap(p->next); // now bucket_[hash].get() == p } return &p->unit; } } return nullptr; } ExternalFileUnit *Find(const char *path, std::size_t pathLen); ExternalFileUnit &Create(int, const Terminator &); Lock lock_; bool isInitialized_{false}; OwningPtr<Chain> bucket_[buckets_]{}; // all owned by *this OwningPtr<Chain> closing_{nullptr}; // units during CLOSE statement common::FastIntSet<maxNewUnits_> freeNewUnits_; int emergencyNewUnit_{maxNewUnits_}; // not recycled }; } // namespace Fortran::runtime::io #endif // FORTRAN_RUNTIME_UNIT_MAP_H_