brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · fa61288 Raw
104 lines · c
1//===-- lib/runtime/unit-map.h ----------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// Maps Fortran unit numbers to their ExternalFileUnit instances.10// A simple hash table with forward-linked chains per bucket.11 12#ifndef FLANG_RT_RUNTIME_UNIT_MAP_H_13#define FLANG_RT_RUNTIME_UNIT_MAP_H_14 15#include "unit.h"16#include "flang-rt/runtime/lock.h"17#include "flang-rt/runtime/memory.h"18#include "flang/Common/fast-int-set.h"19#include <cstdint>20#include <cstdlib>21 22namespace Fortran::runtime::io {23 24class UnitMap {25public:26  ExternalFileUnit *LookUp(int n) {27    CriticalSection critical{lock_};28    return Find(n);29  }30 31  ExternalFileUnit *LookUpOrCreate(32      int n, const Terminator &terminator, bool &wasExtant) {33    CriticalSection critical{lock_};34    if (auto *p{Find(n)}) {35      wasExtant = true;36      return p;37    } else {38      wasExtant = false;39      return n >= 0 ? &Create(n, terminator) : nullptr;40    }41  }42 43  // Unit look-up by name is needed for INQUIRE(FILE="...")44  ExternalFileUnit *LookUp(const char *path, std::size_t pathLen) {45    CriticalSection critical{lock_};46    return Find(path, pathLen);47  }48 49  ExternalFileUnit &NewUnit(const Terminator &);50 51  // To prevent races, the unit is removed from the map if it exists,52  // and put on the closing_ list until DestroyClosed() is called.53  ExternalFileUnit *LookUpForClose(int);54 55  void DestroyClosed(ExternalFileUnit &);56  void CloseAll(IoErrorHandler &);57  void FlushAll(IoErrorHandler &);58 59private:60  struct Chain {61    explicit Chain(int n) : unit{n} {}62    ExternalFileUnit unit;63    OwningPtr<Chain> next{nullptr};64  };65 66  static constexpr int buckets_{1031}; // must be prime67 68  // The pool of recyclable new unit numbers uses the range that69  // works even with INTEGER(kind=1).  0 and -1 are never used.70  static constexpr int maxNewUnits_{129}; // [ -128 .. 0 ]71 72  int Hash(int n) { return std::abs(n) % buckets_; }73 74  void Initialize();75 76  ExternalFileUnit *Find(int n) {77    Chain *previous{nullptr};78    int hash{Hash(n)};79    for (Chain *p{bucket_[hash].get()}; p; previous = p, p = p->next.get()) {80      if (p->unit.unitNumber() == n) {81        if (previous) {82          // Move found unit to front of chain for quicker lookup next time83          previous->next.swap(p->next); // now p->next.get() == p84          bucket_[hash].swap(p->next); // now bucket_[hash].get() == p85        }86        return &p->unit;87      }88    }89    return nullptr;90  }91  ExternalFileUnit *Find(const char *path, std::size_t pathLen);92 93  ExternalFileUnit &Create(int, const Terminator &);94 95  Lock lock_;96  bool isInitialized_{false};97  OwningPtr<Chain> bucket_[buckets_]{}; // all owned by *this98  OwningPtr<Chain> closing_{nullptr}; // units during CLOSE statement99  common::FastIntSet<maxNewUnits_> freeNewUnits_;100  int emergencyNewUnit_{maxNewUnits_}; // not recycled101};102} // namespace Fortran::runtime::io103#endif // FLANG_RT_RUNTIME_UNIT_MAP_H_104