text:
namespace {

namespace cast_crypto = ::extensions::api::cast_crypto;

// Parses |pem_data| for a PEM block of |pem_type|.
// Returns true if a |pem_type| block is found, storing the decoded result in
// |der_output|.
bool GetDERFromPEM(const std::string& pem_data,
                   const std::string& pem_type,
                   std::vector<uint8_t>* der_output) {
  std::vector<std::string> headers;
  headers.push_back(pem_type);
  net::PEMTokenizer pem_tokenizer(pem_data, headers);
  if (!pem_tokenizer.GetNext()) {
    return false;
  }

  der_output->assign(pem_tokenizer.data().begin(), pem_tokenizer.data().end());
  return true;
}

}  // namespace

namespace networking_private_crypto {

bool VerifyCredentials(
    const std::string& certificate,
    const std::vector<std::string>& intermediate_certificates,
    const std::string& signature,
    const std::string& data,
    const std::string& connected_mac) {
  static const char kErrorPrefix[] = "Device verification failed. ";

  std::vector<std::string> headers;
  headers.push_back("CERTIFICATE");

  // Convert certificate from PEM to raw DER
  net::PEMTokenizer pem_tokenizer(certificate, headers);
  if (!pem_tokenizer.GetNext()) {
    LOG(ERROR) << kErrorPrefix << "Failed to parse device certificate.";
    return false;
  }
  std::string der_certificate = pem_tokenizer.data();

  // Convert intermediate certificates from PEM to raw DER
  std::vector<std::string> der_intermediate_certificates;
  for (size_t idx = 0; idx < intermediate_certificates.size(); ++idx) {
    net::PEMTokenizer ica_pem_tokenizer(intermediate_certificates[idx],
                                        headers);
    if (ica_pem_tokenizer.GetNext()) {
      der_intermediate_certificates.push_back(ica_pem_tokenizer.data());
    } else {
      LOG(WARNING) << "Failed to parse intermediate certificates.";
    }
  }

  // Verify device certificate
  scoped_ptr<cast_crypto::CertVerificationContext> verification_context;
  cast_crypto::VerificationResult verification_result =
      cast_crypto::VerifyDeviceCert(der_certificate,
                                    der_intermediate_certificates,
                                    &verification_context);

  if (verification_result.Failure()) {
    LOG(ERROR) << kErrorPrefix << verification_result.error_message;
    return false;
  }

  // Check that the device listed in the certificate is correct.
  // Something like evt_e161 001a11ffacdf
  std::string common_name = verification_context->GetCommonName();
  std::string translated_mac;
  base::RemoveChars(connected_mac, ":", &translated_mac);
  if (!base::EndsWith(common_name, translated_mac,
                      base::CompareCase::INSENSITIVE_ASCII)) {
    LOG(ERROR) << kErrorPrefix << "MAC addresses don't match.";
    return false;
  }

  // Use the public key from verified certificate to verify |signature| over
  // |data|.
  verification_result =
      verification_context->VerifySignatureOverData(signature, data);

  if (verification_result.Failure()) {
    LOG(ERROR) << kErrorPrefix << verification_result.error_message;
    return false;
  }
  return true;
}

bool EncryptByteString(const std::vector<uint8_t>& pub_key_der,
                       const std::string& data,
                       std::vector<uint8_t>* encrypted_output) {
  crypto::EnsureOpenSSLInit();
  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);

  crypto::ScopedRSA rsa(
      RSA_public_key_from_bytes(pub_key_der.data(), pub_key_der.size()));
  if (!rsa || RSA_size(rsa.get()) == 0) {
    LOG(ERROR) << "Failed to parse public key";
    return false;
  }

  encrypted_output->resize(RSA_size(rsa.get()));
  int encrypted_length = RSA_public_encrypt(
      data.size(), reinterpret_cast<const uint8_t*>(data.data()),
      encrypted_output->data(), rsa.get(), RSA_PKCS1_PADDING);
  if (encrypted_length < 0) {
    LOG(ERROR) << "Error during decryption";
    return false;
  }
  encrypted_output->resize(encrypted_length);
  return true;
}

bool DecryptByteString(const std::string& private_key_pem,
                       const std::vector<uint8_t>& encrypted_data,
                       std::string* decrypted_output) {
  crypto::EnsureOpenSSLInit();
  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);

  std::vector<uint8_t> private_key_data;
  if (!GetDERFromPEM(private_key_pem, "PRIVATE KEY", &private_key_data)) {
    LOG(ERROR) << "Failed to parse private key PEM.";
    return false;
  }
  scoped_ptr<crypto::RSAPrivateKey> private_key(
      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(private_key_data));
  if (!private_key || !private_key->key()) {
    LOG(ERROR) << "Failed to parse private key DER.";
    return false;
  }

  crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(private_key->key()));
  if (!rsa || RSA_size(rsa.get()) == 0) {
    LOG(ERROR) << "Failed to get RSA key.";
    return false;
  }

  uint8_t* output = reinterpret_cast<uint8_t*>(
      base::WriteInto(decrypted_output, RSA_size(rsa.get()) + 1));
  int output_length =
      RSA_private_decrypt(encrypted_data.size(), &encrypted_data[0], output,
                          rsa.get(), RSA_PKCS1_PADDING);
  if (output_length < 0) {
    LOG(ERROR) << "Error during decryption.";
    return false;
  }
  decrypted_output->resize(output_length);
  return true;
}

}  // namespace networking_private_crypto


text:
WAX 2016
========

This is the Web site for the [2016 Workshop on Approximate Computing Across the Stack][wax]. It is built using the static site generator [Hugo][].

[wax]: http://approximate.computer/wax2016/
[hugo]: https://gohugo.io/

redpajama_set_name: RedPajamaGithub


text:
package org.motechproject.ivr.exception;

/**
 * The ConfigNotFoundException exception signals a situation when an IVR configuration
 * with a given name cannot be found.
 */
public class ConfigNotFoundException extends RuntimeException {
    private static final long serialVersionUID = 6378022630807925281L;

    public ConfigNotFoundException(String message) {
        super(message);
    }

    public ConfigNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}


text:
package hu.akarnokd.rxjava2.internal.operators.nbp;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import hu.akarnokd.rxjava2.NbpObservable.*;
import hu.akarnokd.rxjava2.Scheduler;
import hu.akarnokd.rxjava2.disposables.Disposable;
import hu.akarnokd.rxjava2.plugins.RxJavaPlugins;

public final class NbpOnSubscribeIntervalRangeSource implements NbpOnSubscribe<Long> {
    final Scheduler scheduler;
    final long start;
    final long end;
    final long initialDelay;
    final long period;
    final TimeUnit unit;

    public NbpOnSubscribeIntervalRangeSource(long start, long end, long initialDelay, long period, TimeUnit unit, Scheduler scheduler) {
        this.initialDelay = initialDelay;
        this.period = period;
        this.unit = unit;
        this.scheduler = scheduler;
        this.start = start;
        this.end = end;
    }

    @Override
    public void accept(NbpSubscriber<? super Long> s) {
        IntervalRangeSubscriber is = new IntervalRangeSubscriber(s, start, end);
        s.onSubscribe(is);

        Disposable d = scheduler.schedulePeriodicallyDirect(is, initialDelay, period, unit);

        is.setResource(d);
    }

    static final class IntervalRangeSubscriber
    implements Disposable, Runnable {

        final NbpSubscriber<? super Long> actual;
        final long end;

        long count;

        volatile boolean cancelled;

        static final Disposable DISPOSED = new Disposable() {
            @Override
            public void dispose() { }
        };

        volatile Disposable resource;
        static final AtomicReferenceFieldUpdater<IntervalRangeSubscriber, Disposable> RESOURCE =
                AtomicReferenceFieldUpdater.newUpdater(IntervalRangeSubscriber.class, Disposable.class, "resource");

        public IntervalRangeSubscriber(NbpSubscriber<? super Long> actual, long start, long end) {
            this.actual = actual;
            this.count = start;
            this.end = end;
        }

        @Override
        public void dispose() {
            if (!cancelled) {
                cancelled = true;
                disposeResource();
            }
        }

        void disposeResource() {
            Disposable d = resource;
            if (d != DISPOSED) {
                d = RESOURCE.getAndSet(this, DISPOSED);
                if (d != DISPOSED && d != null) {
                    d.dispose();
                }
            }
        }

        @Override
        public void run() {
            if (!cancelled) {
                long c = count;
                actual.onNext(c);

                if (c == end) {
                    cancelled = true;
                    try {
                        actual.onComplete();
                    } finally {
                        disposeResource();
                    }
                    return;
                }

                count = c + 1;

            }
        }

        public void setResource(Disposable d) {
            for (;;) {
                Disposable current = resource;
                if (current == DISPOSED) {
                    d.dispose();
                    return;
                }
                if (current != null) {
                    RxJavaPlugins.onError(new IllegalStateException("Resource already set!"));
                    return;
                }
                if (RESOURCE.compareAndSet(this, null, d)) {
                    return;
                }
            }
        }
    }
}


text:
<?php

namespace Parser;

class View extends \Fuel\Core\View
{
	/**
	 * @var  array  Holds the list of loaded files.
	 */
	protected static $loaded_files = array();

	public static function _init()
	{
		// get and normalize the config
		$parser = \Config::load('parser', true);
		foreach (\Config::get('parser.extensions', array()) as $extension => $config)
		{
			if (isset($config['extension']))
			{
				unset($parser['extensions'][$extension]);
				$parser['extensions'][$config['extension']] = $config;
			}
		}
		\Config::set('parser', $parser);

		// Get class name
		$class = \Inflector::denamespace(get_called_class());

		if ($class !== __CLASS__)
		{
			// Include necessary files
			foreach ((array) \Config::get('parser.'.$class.'.include', array()) as $include)
			{
				if ( ! array_key_exists($include, static::$loaded_files))
				{
					require $include;
					static::$loaded_files[$include] = true;
				}
			}
		}
	}

	/**
	 * Forges a new View object based on the extension
	 *
	 * @param   string  $file         view filename
	 * @param   array   $data         view data
	 * @param   bool    $auto_encode  auto encode boolean, null for default
	 * @return  object  a new view instance
	 */
	public static function forge($file = null, $data = null, $auto_encode = null)
	{
		$class = null;
		$extension = 'php';

		if ($file !== null)
		{
			$extension = pathinfo($file, PATHINFO_EXTENSION);
			$class = \Config::get('parser.extensions.'.$extension, null);
		}

		if ($class === null)
		{
			$class = get_called_class();
		}

		// Class can be an array config
		if (is_array($class))
		{
			$class['extension'] and $extension = $class['extension'];
			$class = $class['class'];
		}

		// Include necessary files
		foreach ((array) \Config::get('parser.'.$class.'.include', array()) as $include)
		{
			if ( ! array_key_exists($include, static::$loaded_files))
			{
				require $include;
				static::$loaded_files[$include] = true;
			}
		}

		// Instantiate the Parser class without auto-loading the view file
		if ($auto_encode === null)
		{
			$auto_encode = \Config::get('parser.'.$class.'.auto_encode', null);
		}

		$view = new $class(null, $data, $auto_encode);

		return $view->set_filename($file, true);
	}
}


text:
This changelog references the relevant changes done in 2.x versions.

## v2.0.0
__BREAKING CHANGES__

* Require php 8.1.


text:
/**********************************************
* template class for student projects         *
* author: Marcel Lesch (marcel.lesch@cern.ch) *
**********************************************/

#ifndef ALIANALYSISTASKSTUDENTSML_H
#define ALIANALYSISTASKSTUDENTSML_H

#include "AliAnalysisTaskSE.h"
#include "AliAODTrack.h"
#include "AliAODEvent.h"
#include "AliVEvent.h"
#include "TProfile.h"
#include "TH1F.h"
#include "TH1I.h"
#include "TComplex.h"
#include <TArrayD.h>
#include <vector>
#include "TMath.h"
#include "TF1.h"
#include "TRandom3.h"
#include "AliMCEvent.h"
#include "AliAODMCParticle.h"
#include "AliMCVertex.h"
#include "AliAODVertex.h"
#include "AliCentrality.h"
#include "AliHeader.h"
#include "TExMap.h"
#include "TDirectoryFile.h"
#include "TList.h"
#include "TFile.h"
#include "TSystem.h"

//================================================================================================================

class AliAnalysisTaskStudentsML : public AliAnalysisTaskSE{
 public:

  AliAnalysisTaskStudentsML();
  AliAnalysisTaskStudentsML(const char *name, Bool_t useParticleWeights=kFALSE);
  virtual ~AliAnalysisTaskStudentsML();
  virtual void UserCreateOutputObjects();
  virtual void UserExec(Option_t *);
  virtual void Terminate(Option_t *);

  // 0.) Methods called in the constructor:
  virtual void InitializeArrays();

  // 1.) Methods called in UserCreateOutputObjects():
  virtual void BookAndNestAllLists();
  virtual void BookControlHistograms();
  virtual void BookFinalResultsHistograms();
  virtual void Cosmetics();

  // 2.) Methods called in UserExec(Option_t *) or subsquent Methods:
  virtual void PhysicsAnalysis(AliAODEvent *aAODEvent);
  virtual void GetKineDist(AliAODEvent *aAODEve, AliMCEvent *aMCEve);

  //a) Methods used to assure global quality and track selection
  Bool_t GlobalQualityAssurance(AliAODEvent *aAODevent);
  Bool_t TrackSelection(AliAODTrack *aTrack);
  Bool_t GlobalQualityAssurance(Int_t CentBin, AliMCEvent *aMCKineEvent);
  Bool_t TrackSelection(AliAODMCParticle *aMCtrack);
  Int_t SelectCentrality(AliAODEvent *aAODevent);

  //b) Method used to obtain particle weights
  virtual void CalculateWeight(Int_t CentBin, Int_t RunNumber, Double_t* weights, Int_t Multi, Double_t* angles, Double_t* pt, Double_t* eta);
  Int_t GetRunIndex(Int_t runNumber);
  //c) Methods used for Multi-Particle Correlation Techniques
  virtual void CalculateQvectors(Int_t CalculateQvectors_nParticles, Double_t* CalculateQvectors_angles, Double_t* CalculateQvectors_weights);
  TComplex CalculateMixedQVectors(Double_t Harm, Int_t M_A, Int_t M_B, Double_t* Ang_A, Double_t* Ang_B);
  TComplex Q(Int_t n, Int_t p);
  TComplex Recursion(Int_t n, Int_t* harmonic, Int_t mult, Int_t skip);
  virtual void Correlation(Int_t Number, Int_t h1, Int_t h2, Int_t h3, Int_t h4, Int_t h5, Int_t h6, Int_t h7, Int_t h8, Int_t h9, Int_t h10, Int_t h11, Int_t h12, Int_t h13, Int_t h14, Double_t *Correlation_Data);

  virtual void MainTask(Int_t MainTask_CentBin, Int_t MainTask_Mult, Double_t* MainTask_Angle_Array, Double_t* MainTask_Weight_Array);
  virtual void MixedParticle(Int_t MP_CentBin, Int_t Harmonicus, Int_t Mixed_Mult_A, Double_t* Mixed_Angle_A, Int_t Mixed_Mult_B, Double_t* Mixed_Angle_B);

  // 3.) Methods called in Terminate():
  // ...

  // 4.) Setters and getters:
  void SetDoAnalysis(Bool_t DoAnalysis){this->bDoAnalysis = DoAnalysis; }

  void SetKineSpecifics(Bool_t RicoKineTable, Bool_t UseWeakSecondaries){this->bUseRecoKineTable = RicoKineTable; this->bUseWeakSecondaries = UseWeakSecondaries; }

  void SetSaveAllQA(Bool_t SaveQA){this->bSaveAllQA=SaveQA;}

  void SetBoolMultCut(Bool_t top, Int_t otp){this->bMultCut = top; this->fSecondFilter=otp;}

  void SetUpperLineCut(Float_t slope, Float_t axis)
  {this->fSlopeUpperLine = slope; this->fAxisUpperLine = axis; }

   void SetLowerLineCut(Float_t slope, Float_t axis)
  {this->fSlopeLowerLine = slope; this->fAxisLowerLine = axis; }

  void SetFilter(Int_t top){this->fMainFilter = top;}

  void SetCentralityEstimator(Bool_t Esti){this->fCentralityfromVZero = Esti; }

  void SetUseWeights(Bool_t Weights, Bool_t Phi, Bool_t Pt, Bool_t Eta)
  {this->bUseWeights = Weights; this->bUsePhiWeights = Phi; this->bUsePtWeights = Pt; this->bUseEtaWeights = Eta;}

  void SetVertexX(Bool_t Cut, Double_t Min, Double_t Max)
  {this->bCutOnVertexX=Cut;  this->fMinVertexX=Min; this->fMaxVertexX=Max;}

  void SetVertexY(Bool_t Cut, Double_t Min, Double_t Max)
  {this->bCutOnVertexY=Cut;  this->fMinVertexY=Min; this->fMaxVertexY=Max;}

  void SetVertexZ(Bool_t Cut, Double_t Min, Double_t Max)
  {this->bCutOnVertexZ=Cut;  this->fMinVertexZ=Min; this->fMaxVertexZ=Max;}

   void SetEtaCut(Bool_t Cut, Double_t Min, Double_t Max)
  {this->bCutOnEta=Cut;  this->fMinEtaCut=Min; this->fMaxEtaCut=Max;}

  void SetPtCut(Bool_t Cut, Double_t Min, Double_t Max)
  {this->bCutOnPt=Cut;  this->fMinPtCut=Min; this->fMaxPtCut=Max;}

  void SetNumberTPCClusters(Bool_t Cut, Int_t Min)
  {this->bNumberTPCCluster=Cut;  this->fMinTPCCluster=Min; }

  void SetNumberITSClusters(Bool_t Cut, Int_t Min)
  {this->bNumberITSCluster=Cut;  this->fMinITSCluster=Min; }

  void SetChiSquareTPC(Bool_t Cut, Double_t Min, Double_t Max)
  {this->bChiSquareTPC=Cut;  this->fMinChiSquareTPC=Min; this->fMaxChiSquareTPC=Max;}

  void SetDCAz(Bool_t Cut, Double_t Max)
  {this->bDCAz=Cut;  this->fMaxDCAz=Max;}

  void SetDCAxy(Bool_t Cut, Double_t Max)
  {this->bDCAxy=Cut;  this->fMaxDCAxy=Max;}

  void SetMinNuPar(Int_t top){this->fMinNumberPart = top;}
  Int_t GetMinNuPar() const {return this->fMinNumberPart;}

   void SetCorrSet1(Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  {this->fNumber=Number; this->fa1=a; this->fa2=b; this->fa3=c; this->fa4=d; this->fa5=e; this->fa6=f; this->fa7=g;}

  void SetCorrSet2( Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  { this->fNumberSecond=Number; this->fb1=a; this->fb2=b; this->fb3=c; this->fb4=d; this->fb5=e; this->fb6=f; this->fb7=g;}

  void SetCorrSet3( Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  { this->fNumberThird=Number; this->fd1=a; this->fd2=b; this->fd3=c; this->fd4=d; this->fd5=e; this->fd6=f; this->fd7=g;}

  void SetCorrSet4( Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  { this->fNumberFourth=Number; this->fe1=a; this->fe2=b; this->fe3=c; this->fe4=d; this->fe5=e; this->fe6=f; this->fe7=g;}

  void SetCorrSet5(Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  {this->fNumberFifth=Number; this->ff1=a; this->ff2=b; this->ff3=c; this->ff4=d; this->ff5=e; this->ff6=f; this->ff7=g;}

  void SetCorrSet6(Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  {this->fNumberSixth=Number; this->fg1=a; this->fg2=b; this->fg3=c; this->fg4=d; this->fg5=e; this->fg6=f; this->fg7=g;}

  void SetCorrSet7(Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  {this->fNumberSeventh=Number; this->fh1=a; this->fh2=b; this->fh3=c; this->fh4=d; this->fh5=e; this->fh6=f; this->fh7=g;}

  void SetCorrSet8(Int_t Number, Int_t a, Int_t b, Int_t c, Int_t d, Int_t e, Int_t f, Int_t g)
  {this->fNumberEighth=Number; this->fi1=a; this->fi2=b; this->fi3=c; this->fi4=d; this->fi5=e; this->fi6=f; this->fi7=g;}

  void SetMixed(Bool_t top, Int_t nop, Bool_t DifferentCharge, Bool_t PositiveCharge)
  {this->bDoMixed = top; this->fMixedHarmonic = nop; this->bDifferentCharge = DifferentCharge;
	this->bSetSameChargePositiv = PositiveCharge;	}

  void SetCentrality(Float_t cen0, Float_t cen1, Float_t cen2, Float_t cen3, Float_t cen4, Float_t cen5, Float_t cen6, Float_t cen7, Float_t cen8, Float_t cen9, Float_t cen10, Float_t cen11, Float_t cen12, Float_t cen13, Float_t cen14, Float_t cen15, Float_t cen16 )
 {this->fcent_0 = cen0; this->fcent_1 = cen1; this->fcent_2 = cen2; this->fcent_3 = cen3; this->fcent_4 = cen4; this->fcent_5 = cen5; this->fcent_6 = cen6; this->fcent_7 = cen7; this->fcent_8 = cen8; this->fcent_9 = cen9; this->fcent_10 = cen10; this->fcent_11 = cen11; this->fcent_12 = cen12; this->fcent_13 = cen13; this->fcent_14 = cen14; this->fcent_15 = cen15; this->fcent_16 = cen16;}

  void SetListOfRuns(TString dataPeriod);

  void SetInputParticleWeights(TString fileWeight); //Set weight files that should be accessed

  void SetInitializeCentralityArray(); //Set Centrality array

 private:
  AliAnalysisTaskStudentsML(const AliAnalysisTaskStudentsML& aatmpf);
  AliAnalysisTaskStudentsML& operator=(const AliAnalysisTaskStudentsML& aatmpf);

  // 0.) Base lists:
  TList *fHistList; // base list to hold all output object (a.k.a. grandmother of all lists)

  // 1.) Control histograms:
  TList *fCentralityList[16];		//! Will be one list per certain centrality bin. Up to 16 centraliy bins possible
  TList *fControlHistogramsList[16]; 	//! List to hold all control histograms for a specific centrality bin. Up to 16 centraliy bins possible

  TH1F *fPTHistogram[16][4]; 		//! 0: P_t Before Track Selection, 1: P_t After Track Selection, 2: P_t Before Track Selection (second), 3: P_t After Track Selection (second);
  TH1F *fPhiHistogram[16][4]; 		//! 0: Phi Before Track Selection, 1: Phi After Track Selection, 2: Phi Before Track Selection (second), 3: Phi After Track Selection (second);
  TH1F *fEtaHistogram[16][4]; 		//! 0: Eta Before Track Selection, 1: Eta After Track Selection, 2: Eta Before Track Selection (second), 3: Eta After Track Selection (second);
  TH1F *fMultHistogram[16][4]; 		//! 0: Multiplicity before HMO removel 1: Multiplicity Before Track Selection, 2: Mult. After Track Selection 3: Mult. After Track Selection (second);
  TH1F *fTPCClustersHistogram[16][2]; 	//! 0: TPC Clusters Before Track Selection, 1: TPC Clusters After Track Selection
  TH1F *fITSClustersHistogram[16][2]; 	//! 0: ITS Clusters Before Track Selection, 1: ITS Clusters After Track Selection
  TH1F *fChiSquareTPCHistogram[16][2]; 	//! 0: ChiSquare TPC Before Track Selection, 1: ChiSquare TPC After Track Selection
  TH1F *fDCAzHistogram[16][2]; 		//! 0: DCAz Before Track Selection, 1: DCAz After Track Selection
  TH1F *fDCAxyHistogram[16][2]; 	//! 0: DCAxy Before Track Selection, 1: DCAxy After Track Selection
  TH1F *fCentralityHistogram[16]; 	//! Centrality After Corresponding Cut
  TH1F *fCentralityHistogramBefore;     //! Centrality Histogram before Centrality selection

  //2.) SelectionCuts
  Bool_t bDoAnalysis;			// if kTRUE: Run of AODs (real Data or MC on Recon level) Does Analysis, if kFALSE: Get Weights
  Bool_t bUseRecoKineTable;		// (Necessary if bDoAnalysis = kFALSE) if kTRUE: use the kine-reco mapping table (for kine level)
  Bool_t bUseWeakSecondaries; 		// if kTRUE: use weak secondaries for obtaining weights, if kFALSE: only primaries
  Bool_t bSaveAllQA;			// if kTRUE: All Standard QA Histograms are saved (default kTRUE)
  Bool_t bMultCut;			// Cut to remove HMO's
  Int_t fMainFilter;           		// for main filter selection (default: Hypbrid)
  Int_t fSecondFilter;           	// for filter selection (default: global)
  Float_t fSlopeUpperLine;          	// slope of the upper line for multiplicity cut
  Float_t fAxisUpperLine;          	// axis intercept of the upper line for multiplicity cut
  Float_t fSlopeLowerLine;          	// slope of the lower line for multiplicity cut
  Float_t fAxisLowerLine;           	// axis intercept of the lower line for multiplicity cut

    //Centrality
  Float_t fcent_0, fcent_1, fcent_2, fcent_3, fcent_4, fcent_5, fcent_6, fcent_7, fcent_8, fcent_9, fcent_10, fcent_11, fcent_12, fcent_13, fcent_14, fcent_15, fcent_16;
  					//fcent_i holds the edge of a centrality bin
  Int_t fCentralityBins;		//will be set to 16, for at maximum 16 bins in case of centrality 0 to 80 in 5% steps. Less bins and different steps may be used
  Float_t fcentralityArray[17];		//will hold our edges of the centrality bins

    //Global
  Bool_t bCutOnVertexX;               	// Bool to apply Vertex Cut in X (default kFALSE)
  Bool_t bCutOnVertexY;               	// Bool to apply Vertex Cut in Y (default kFALSE)
  Bool_t bCutOnVertexZ;               	// Bool to apply Vertex Cut in Z (default kFALSE)
  Double_t fMinVertexX;               	// min vertex cut X (default -44)
  Double_t fMaxVertexX;               	// max vertex cut X (default -44)
  Double_t fMinVertexY;               	// min vertex cut Y (default -44)
  Double_t fMaxVertexY;               	// max vertex cut Y (default -44)
  Double_t fMinVertexZ;               	// min vertex cut Z (default -10 cm)
  Double_t fMaxVertexZ;               	// max vertex cut Z (default +10 cm)
  TH1F *fVertexXHistogram[16][2];       //! 0: Vertex X Before Corresponding, 1: Vertex X After Corresponding Cut
  TH1F *fVertexYHistogram[16][2];       //! 0: Vertex Y Before Corresponding, 1: Vertex Y After Corresponding Cut
  TH1F *fVertexZHistogram[16][2];       //! 0: Vertex Z Before Corresponding, 1: Vertex Z After Corresponding Cut

  Bool_t fCentralityfromVZero;	     	// if kTRUE: Use V0 as centrality estimator, if kFALSE: SPD Cluster

    //Physics-Selection
  Bool_t bCutOnEta;               	// Bool to apply eta cuts (default kTRUE)
  Bool_t bCutOnPt;               	// Bool to apply pt cuts (default kTRUE)
  Bool_t bNumberTPCCluster;		// Bool to apply cuts on number of TPC clusters (default kTRUE)
  Bool_t bNumberITSCluster;		// Bool to apply cuts on number of ITS clusters (default kTRUE)
  Bool_t bChiSquareTPC;			// Bool to apply cuts on chi square TPC (default kTRUE)
  Bool_t bDCAz;				// Bool to apply cuts on DCAz (default kTRUE)
  Bool_t bDCAxy;			// Bool to apply cuts on DCAxy (default kTRUE)
  Double_t fMinEtaCut;               	// min eta cut (default -0.8)
  Double_t fMaxEtaCut;               	// max eta cut (default 0.8)
  Double_t fMinPtCut;               	// min pt cut (default 0.2)
  Double_t fMaxPtCut;               	// max pt cut (default 5.0)
  Int_t fMinTPCCluster;			// Number of minimum TPC clusters (default 70)
  Int_t fMinITSCluster;			// Number of minimum ITS clusters (default 2)
  Double_t fMinChiSquareTPC;		// Minimal Chi Square TPC (default 0.1)
  Double_t fMaxChiSquareTPC;		// Maximal Chi Square TPC (default 4.0)
  Double_t fMaxDCAz;			// Maximal DCAz (default 3.2 cm)
  Double_t fMaxDCAxy;			// Maximal DCAxy (default 2.4 cm)

  //Weights
  Bool_t bUseWeights;
  Bool_t bUsePtWeights;
  Bool_t bUsePhiWeights;
  Bool_t bUseEtaWeights;
  Int_t fNumberRuns;           	    // Number of runs in the dataset.
  Int_t fListRuns[90];              // List of runs in the dataset.
  TH1F *fHistoPtWeight[16][90];     // Histograms with the pT-weights for each run.
  TH1F *fHistoEtaWeight[16][90];    // Histograms with the eta-weights for each run.
  TH1F *fHistoPhiWeight[16][90];    // Histograms with the phi-weights for each run.

  //3.) Variables for the correlation:
  Int_t fMaxCorrelator;          	// maximum of correlation

  Int_t fNumber;           		// Number of correlation first correlator
  Int_t fNumberSecond;          	// Number of correlation second correlator
  Int_t fNumberThird;           	// Number of correlation third correlator
  Int_t fNumberFourth;			// Number of correlation fourth correlator
  Int_t fNumberFifth;			// Number of correlation fifth correlator
  Int_t fNumberSixth;			// Number of correlation sixth correlator
  Int_t fNumberSeventh;			// Number of correlation seventh correlator
  Int_t fNumberEighth;			// Number of correlation eigth correlator
  Int_t fMinNumberPart;           	// Minimal number of particles to do correlation

  Int_t fa1, fa2, fa3, fa4, fa5, fa6, fa7; //first set of harmonics
  Int_t fb1, fb2, fb3, fb4, fb5, fb6, fb7; //second set of harmonics
  Int_t fd1, fd2, fd3, fd4, fd5, fd6, fd7; //third set of harmonics
  Int_t fe1, fe2, fe3, fe4, fe5, fe6, fe7; //fourth set of harmonics
  Int_t ff1, ff2, ff3, ff4, ff5, ff6, ff7;  //sixth set of harmonics
  Int_t fg1, fg2, fg3, fg4, fg5, fg6, fg7;  //seventh set of harmonics
  Int_t fh1, fh2, fh3, fh4, fh5, fh6, fh7;  //harmonics
  Int_t fi1, fi2, fi3, fi4, fi5, fi6, fi7;  //eigth set of harmonics

  TComplex fQvector[85][15];       	// //[fMaxHarmonic*fMaxCorrelator+1][fMaxCorrelator+1]

  // 4.) Final results:

  TProfile *fResults[16];         	//! final centrality result
  TProfile *fMixedParticleHarmonics[16];//! Stores output for special mixed particle analysis
  Bool_t bDoMixed;		 	// if kTRUE: Do special mixed particle analysis, default kFALSE (MainTask)
  Bool_t bDifferentCharge; 	 	// used in DoMixed: if kTRUE mixed particle analysis between positiv and negativ
				 	//		    if kFALSE mixed particle analysis between same charge
				 	//		    (only positiv or only negativ particles)
				 	// Default kTRUE
  Bool_t bSetSameChargePositiv;   	// used if bDifferentCharge: if kTRUE use positiv, if kFALSE use negative (default kTRUE)
  Int_t fMixedHarmonic;			// Harmonic of special mixed particle analysis
  TH1F *fCounterHistogram;       	//! for some checks
  TList *fFinalResultsList[16];      	//! List to hold all histograms with final results for a specific centrality bin. Up to 16 centraliy bins possible

  ClassDef(AliAnalysisTaskStudentsML,31);

};

//================================================================================================================

#endif


text:
"""Tests for system APIS."""

import contextlib
import datetime
import errno
import os
import platform
import pprint
import shutil
import signal
import socket
import sys
import time
import unittest

import psutil
from psutil import AIX
from psutil import BSD
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import FileNotFoundError
from psutil._compat import long
from psutil.tests import ASCII_FS
from psutil.tests import CI_TESTING
from psutil.tests import DEVNULL
from psutil.tests import GITHUB_ACTIONS
from psutil.tests import GLOBAL_TIMEOUT
from psutil.tests import HAS_BATTERY
from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_GETLOADAVG
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_SENSORS_BATTERY
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import IS_64BIT
from psutil.tests import MACOS_12PLUS
from psutil.tests import PYPY
from psutil.tests import UNICODE_SUFFIX
from psutil.tests import PsutilTestCase
from psutil.tests import check_net_address
from psutil.tests import enum
from psutil.tests import mock
from psutil.tests import retry_on_failure

# ===================================================================
# --- System-related API tests
# ===================================================================

class TestProcessAPIs(PsutilTestCase):

    def test_process_iter(self):
        self.assertIn(os.getpid(), [x.pid for x in psutil.process_iter()])
        sproc = self.spawn_testproc()
        self.assertIn(sproc.pid, [x.pid for x in psutil.process_iter()])
        p = psutil.Process(sproc.pid)
        p.kill()
        p.wait()
        self.assertNotIn(sproc.pid, [x.pid for x in psutil.process_iter()])

        with mock.patch('psutil.Process',
                        side_effect=psutil.NoSuchProcess(os.getpid())):
            self.assertEqual(list(psutil.process_iter()), [])
        with mock.patch('psutil.Process',
                        side_effect=psutil.AccessDenied(os.getpid())):
            with self.assertRaises(psutil.AccessDenied):
                list(psutil.process_iter())

    def test_prcess_iter_w_attrs(self):
        for p in psutil.process_iter(attrs=['pid']):
            self.assertEqual(list(p.info.keys()), ['pid'])
        with self.assertRaises(ValueError):
            list(psutil.process_iter(attrs=['foo']))
        with mock.patch("psutil._psplatform.Process.cpu_times",
                        side_effect=psutil.AccessDenied(0, "")) as m:
            for p in psutil.process_iter(attrs=["pid", "cpu_times"]):
                self.assertIsNone(p.info['cpu_times'])
                self.assertGreaterEqual(p.info['pid'], 0)
            assert m.called
        with mock.patch("psutil._psplatform.Process.cpu_times",
                        side_effect=psutil.AccessDenied(0, "")) as m:
            flag = object()
            for p in psutil.process_iter(
                    attrs=["pid", "cpu_times"], ad_value=flag):
                self.assertIs(p.info['cpu_times'], flag)
                self.assertGreaterEqual(p.info['pid'], 0)
            assert m.called

    @unittest.skipIf(PYPY and WINDOWS,
                     "spawn_testproc() unreliable on PYPY + WINDOWS")
    def test_wait_procs(self):
        def callback(p):
            pids.append(p.pid)

        pids = []
        sproc1 = self.spawn_testproc()
        sproc2 = self.spawn_testproc()
        sproc3 = self.spawn_testproc()
        procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)]
        self.assertRaises(ValueError, psutil.wait_procs, procs, timeout=-1)
        self.assertRaises(TypeError, psutil.wait_procs, procs, callback=1)
        t = time.time()
        gone, alive = psutil.wait_procs(procs, timeout=0.01, callback=callback)

        self.assertLess(time.time() - t, 0.5)
        self.assertEqual(gone, [])
        self.assertEqual(len(alive), 3)
        self.assertEqual(pids, [])
        for p in alive:
            self.assertFalse(hasattr(p, 'returncode'))

        @retry_on_failure(30)
        def test(procs, callback):
            gone, alive = psutil.wait_procs(procs, timeout=0.03,
                                            callback=callback)
            self.assertEqual(len(gone), 1)
            self.assertEqual(len(alive), 2)
            return gone, alive

        sproc3.terminate()
        gone, alive = test(procs, callback)
        self.assertIn(sproc3.pid, [x.pid for x in gone])
        if POSIX:
            self.assertEqual(gone.pop().returncode, -signal.SIGTERM)
        else:
            self.assertEqual(gone.pop().returncode, 1)
        self.assertEqual(pids, [sproc3.pid])
        for p in alive:
            self.assertFalse(hasattr(p, 'returncode'))

        @retry_on_failure(30)
        def test(procs, callback):
            gone, alive = psutil.wait_procs(procs, timeout=0.03,
                                            callback=callback)
            self.assertEqual(len(gone), 3)
            self.assertEqual(len(alive), 0)
            return gone, alive

        sproc1.terminate()
        sproc2.terminate()
        gone, alive = test(procs, callback)
        self.assertEqual(set(pids), set([sproc1.pid, sproc2.pid, sproc3.pid]))
        for p in gone:
            self.assertTrue(hasattr(p, 'returncode'))

    @unittest.skipIf(PYPY and WINDOWS,
                     "spawn_testproc() unreliable on PYPY + WINDOWS")
    def test_wait_procs_no_timeout(self):
        sproc1 = self.spawn_testproc()
        sproc2 = self.spawn_testproc()
        sproc3 = self.spawn_testproc()
        procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)]
        for p in procs:
            p.terminate()
        gone, alive = psutil.wait_procs(procs)

    def test_pid_exists(self):
        sproc = self.spawn_testproc()
        self.assertTrue(psutil.pid_exists(sproc.pid))
        p = psutil.Process(sproc.pid)
        p.kill()
        p.wait()
        self.assertFalse(psutil.pid_exists(sproc.pid))
        self.assertFalse(psutil.pid_exists(-1))
        self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids())

    def test_pid_exists_2(self):
        pids = psutil.pids()
        for pid in pids:
            try:
                assert psutil.pid_exists(pid)
            except AssertionError:
                # in case the process disappeared in meantime fail only
                # if it is no longer in psutil.pids()
                time.sleep(.1)
                self.assertNotIn(pid, psutil.pids())
        pids = range(max(pids) + 5000, max(pids) + 6000)
        for pid in pids:
            self.assertFalse(psutil.pid_exists(pid), msg=pid)

class TestMiscAPIs(PsutilTestCase):

    def test_boot_time(self):
        bt = psutil.boot_time()
        self.assertIsInstance(bt, float)
        self.assertGreater(bt, 0)
        self.assertLess(bt, time.time())

    @unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI")
    def test_users(self):
        users = psutil.users()
        self.assertNotEqual(users, [])
        for user in users:
            assert user.name, user
            self.assertIsInstance(user.name, str)
            self.assertIsInstance(user.terminal, (str, type(None)))
            if user.host is not None:
                self.assertIsInstance(user.host, (str, type(None)))
            user.terminal
            user.host
            assert user.started > 0.0, user
            datetime.datetime.fromtimestamp(user.started)
            if WINDOWS or OPENBSD:
                self.assertIsNone(user.pid)
            else:
                psutil.Process(user.pid)

    def test_test(self):
        # test for psutil.test() function
        stdout = sys.stdout
        sys.stdout = DEVNULL
        try:
            psutil.test()
        finally:
            sys.stdout = stdout

    def test_os_constants(self):
        names = ["POSIX", "WINDOWS", "LINUX", "MACOS", "FREEBSD", "OPENBSD",
                 "NETBSD", "BSD", "SUNOS"]
        for name in names:
            self.assertIsInstance(getattr(psutil, name), bool, msg=name)

        if os.name == 'posix':
            assert psutil.POSIX
            assert not psutil.WINDOWS
            names.remove("POSIX")
            if "linux" in sys.platform.lower():
                assert psutil.LINUX
                names.remove("LINUX")
            elif "bsd" in sys.platform.lower():
                assert psutil.BSD
                self.assertEqual([psutil.FREEBSD, psutil.OPENBSD,
                                  psutil.NETBSD].count(True), 1)
                names.remove("BSD")
                names.remove("FREEBSD")
                names.remove("OPENBSD")
                names.remove("NETBSD")
            elif "sunos" in sys.platform.lower() or \
                    "solaris" in sys.platform.lower():
                assert psutil.SUNOS
                names.remove("SUNOS")
            elif "darwin" in sys.platform.lower():
                assert psutil.MACOS
                names.remove("MACOS")
        else:
            assert psutil.WINDOWS
            assert not psutil.POSIX
            names.remove("WINDOWS")

        # assert all other constants are set to False
        for name in names:
            self.assertIs(getattr(psutil, name), False, msg=name)

class TestMemoryAPIs(PsutilTestCase):

    def test_virtual_memory(self):
        mem = psutil.virtual_memory()
        assert mem.total > 0, mem
        assert mem.available > 0, mem
        assert 0 <= mem.percent <= 100, mem
        assert mem.used > 0, mem
        assert mem.free >= 0, mem
        for name in mem._fields:
            value = getattr(mem, name)
            if name != 'percent':
                self.assertIsInstance(value, (int, long))
            if name != 'total':
                if not value >= 0:
                    raise self.fail("%r < 0 (%s)" % (name, value))
                if value > mem.total:
                    raise self.fail("%r > total (total=%s, %s=%s)"
                                    % (name, mem.total, name, value))

    def test_swap_memory(self):
        mem = psutil.swap_memory()
        self.assertEqual(
            mem._fields, ('total', 'used', 'free', 'percent', 'sin', 'sout'))

        assert mem.total >= 0, mem
        assert mem.used >= 0, mem
        if mem.total > 0:
            # likely a system with no swap partition
            assert mem.free > 0, mem
        else:
            assert mem.free == 0, mem
        assert 0 <= mem.percent <= 100, mem
        assert mem.sin >= 0, mem
        assert mem.sout >= 0, mem

class TestCpuAPIs(PsutilTestCase):

    def test_cpu_count_logical(self):
        logical = psutil.cpu_count()
        self.assertIsNotNone(logical)
        self.assertEqual(logical, len(psutil.cpu_times(percpu=True)))
        self.assertGreaterEqual(logical, 1)
        #
        if os.path.exists("/proc/cpuinfo"):
            with open("/proc/cpuinfo") as fd:
                cpuinfo_data = fd.read()
            if "physical id" not in cpuinfo_data:
                raise unittest.SkipTest("cpuinfo doesn't include physical id")

    def test_cpu_count_cores(self):
        logical = psutil.cpu_count()
        cores = psutil.cpu_count(logical=False)
        if cores is None:
            raise self.skipTest("cpu_count_cores() is None")
        if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1):  # <= Vista
            self.assertIsNone(cores)
        else:
            self.assertGreaterEqual(cores, 1)
            self.assertGreaterEqual(logical, cores)

    def test_cpu_count_none(self):
        # https://github.com/giampaolo/psutil/issues/1085
        for val in (-1, 0, None):
            with mock.patch('psutil._psplatform.cpu_count_logical',
                            return_value=val) as m:
                self.assertIsNone(psutil.cpu_count())
                assert m.called
            with mock.patch('psutil._psplatform.cpu_count_cores',
                            return_value=val) as m:
                self.assertIsNone(psutil.cpu_count(logical=False))
                assert m.called

    def test_cpu_times(self):
        # Check type, value >= 0, str().
        total = 0
        times = psutil.cpu_times()
        sum(times)
        for cp_time in times:
            self.assertIsInstance(cp_time, float)
            self.assertGreaterEqual(cp_time, 0.0)
            total += cp_time
        self.assertEqual(total, sum(times))
        str(times)
        # CPU times are always supposed to increase over time
        # or at least remain the same and that's because time
        # cannot go backwards.
        # Surprisingly sometimes this might not be the case (at
        # least on Windows and Linux), see:
        # https://github.com/giampaolo/psutil/issues/392
        # https://github.com/giampaolo/psutil/issues/645
        # if not WINDOWS:
        #     last = psutil.cpu_times()
        #     for x in range(100):
        #         new = psutil.cpu_times()
        #         for field in new._fields:
        #             new_t = getattr(new, field)
        #             last_t = getattr(last, field)
        #             self.assertGreaterEqual(new_t, last_t,
        #                                     msg="%s %s" % (new_t, last_t))
        #         last = new

    def test_cpu_times_time_increases(self):
        # Make sure time increases between calls.
        t1 = sum(psutil.cpu_times())
        stop_at = time.time() + GLOBAL_TIMEOUT
        while time.time() < stop_at:
            t2 = sum(psutil.cpu_times())
            if t2 > t1:
                return
        raise self.fail("time remained the same")

    def test_per_cpu_times(self):
        # Check type, value >= 0, str().
        for times in psutil.cpu_times(percpu=True):
            total = 0
            sum(times)
            for cp_time in times:
                self.assertIsInstance(cp_time, float)
                self.assertGreaterEqual(cp_time, 0.0)
                total += cp_time
            self.assertEqual(total, sum(times))
            str(times)
        self.assertEqual(len(psutil.cpu_times(percpu=True)[0]),
                         len(psutil.cpu_times(percpu=False)))

        # Note: in theory CPU times are always supposed to increase over
        # time or remain the same but never go backwards. In practice
        # sometimes this is not the case.
        # This issue seemd to be afflict Windows:
        # https://github.com/giampaolo/psutil/issues/392
        # ...but it turns out also Linux (rarely) behaves the same.
        # last = psutil.cpu_times(percpu=True)
        # for x in range(100):
        #     new = psutil.cpu_times(percpu=True)
        #     for index in range(len(new)):
        #         newcpu = new[index]
        #         lastcpu = last[index]
        #         for field in newcpu._fields:
        #             new_t = getattr(newcpu, field)
        #             last_t = getattr(lastcpu, field)
        #             self.assertGreaterEqual(
        #                 new_t, last_t, msg="%s %s" % (lastcpu, newcpu))
        #     last = new

    def test_per_cpu_times_2(self):
        # Simulate some work load then make sure time have increased
        # between calls.
        tot1 = psutil.cpu_times(percpu=True)
        giveup_at = time.time() + GLOBAL_TIMEOUT
        while True:
            if time.time() >= giveup_at:
                return self.fail("timeout")
            tot2 = psutil.cpu_times(percpu=True)
            for t1, t2 in zip(tot1, tot2):
                t1, t2 = psutil._cpu_busy_time(t1), psutil._cpu_busy_time(t2)
                difference = t2 - t1
                if difference >= 0.05:
                    return

    def test_cpu_times_comparison(self):
        # Make sure the sum of all per cpu times is almost equal to
        # base "one cpu" times.
        base = psutil.cpu_times()
        per_cpu = psutil.cpu_times(percpu=True)
        summed_values = base._make([sum(num) for num in zip(*per_cpu)])
        for field in base._fields:
            self.assertAlmostEqual(
                getattr(base, field), getattr(summed_values, field), delta=1)

    def _test_cpu_percent(self, percent, last_ret, new_ret):
        try:
            self.assertIsInstance(percent, float)
            self.assertGreaterEqual(percent, 0.0)
            self.assertIsNot(percent, -0.0)
            self.assertLessEqual(percent, 100.0 * psutil.cpu_count())
        except AssertionError as err:
            raise AssertionError("\n%s\nlast=%s\nnew=%s" % (
                err, pprint.pformat(last_ret), pprint.pformat(new_ret)))

    def test_cpu_percent(self):
        last = psutil.cpu_percent(interval=0.001)
        for x in range(100):
            new = psutil.cpu_percent(interval=None)
            self._test_cpu_percent(new, last, new)
            last = new
        with self.assertRaises(ValueError):
            psutil.cpu_percent(interval=-1)

    def test_per_cpu_percent(self):
        last = psutil.cpu_percent(interval=0.001, percpu=True)
        self.assertEqual(len(last), psutil.cpu_count())
        for x in range(100):
            new = psutil.cpu_percent(interval=None, percpu=True)
            for percent in new:
                self._test_cpu_percent(percent, last, new)
            last = new
        with self.assertRaises(ValueError):
            psutil.cpu_percent(interval=-1, percpu=True)

    def test_cpu_times_percent(self):
        last = psutil.cpu_times_percent(interval=0.001)
        for x in range(100):
            new = psutil.cpu_times_percent(interval=None)
            for percent in new:
                self._test_cpu_percent(percent, last, new)
            self._test_cpu_percent(sum(new), last, new)
            last = new
        with self.assertRaises(ValueError):
            psutil.cpu_times_percent(interval=-1)

    def test_per_cpu_times_percent(self):
        last = psutil.cpu_times_percent(interval=0.001, percpu=True)
        self.assertEqual(len(last), psutil.cpu_count())
        for x in range(100):
            new = psutil.cpu_times_percent(interval=None, percpu=True)
            for cpu in new:
                for percent in cpu:
                    self._test_cpu_percent(percent, last, new)
                self._test_cpu_percent(sum(cpu), last, new)
            last = new

    def test_per_cpu_times_percent_negative(self):
        # see: https://github.com/giampaolo/psutil/issues/645
        psutil.cpu_times_percent(percpu=True)
        zero_times = [x._make([0 for x in range(len(x._fields))])
                      for x in psutil.cpu_times(percpu=True)]
        with mock.patch('psutil.cpu_times', return_value=zero_times):
            for cpu in psutil.cpu_times_percent(percpu=True):
                for percent in cpu:
                    self._test_cpu_percent(percent, None, None)

    def test_cpu_stats(self):
        # Tested more extensively in per-platform test modules.
        infos = psutil.cpu_stats()
        self.assertEqual(
            infos._fields,
            ('ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'))
        for name in infos._fields:
            value = getattr(infos, name)
            self.assertGreaterEqual(value, 0)
            # on AIX, ctx_switches is always 0
            if not AIX and name in ('ctx_switches', 'interrupts'):
                self.assertGreater(value, 0)

    # TODO: remove this once 1892 is fixed
    @unittest.skipIf(MACOS and platform.machine() == 'arm64',
                     "skipped due to #1892")
    @unittest.skipIf(not HAS_CPU_FREQ, "not supported")
    def test_cpu_freq(self):
        def check_ls(ls):
            for nt in ls:
                self.assertEqual(nt._fields, ('current', 'min', 'max'))
                if nt.max != 0.0:
                    self.assertLessEqual(nt.current, nt.max)
                for name in nt._fields:
                    value = getattr(nt, name)
                    self.assertIsInstance(value, (int, long, float))
                    self.assertGreaterEqual(value, 0)

        ls = psutil.cpu_freq(percpu=True)
        if FREEBSD and not ls:
            raise self.skipTest("returns empty list on FreeBSD")

        assert ls, ls
        check_ls([psutil.cpu_freq(percpu=False)])

        if LINUX:
            self.assertEqual(len(ls), psutil.cpu_count())

    @unittest.skipIf(not HAS_GETLOADAVG, "not supported")
    def test_getloadavg(self):
        loadavg = psutil.getloadavg()
        self.assertEqual(len(loadavg), 3)
        for load in loadavg:
            self.assertIsInstance(load, float)
            self.assertGreaterEqual(load, 0.0)

class TestDiskAPIs(PsutilTestCase):

    @unittest.skipIf(PYPY and not IS_64BIT, "unreliable on PYPY32 + 32BIT")
    def test_disk_usage(self):
        usage = psutil.disk_usage(os.getcwd())
        self.assertEqual(usage._fields, ('total', 'used', 'free', 'percent'))

        assert usage.total > 0, usage
        assert usage.used > 0, usage
        assert usage.free > 0, usage
        assert usage.total > usage.used, usage
        assert usage.total > usage.free, usage
        assert 0 <= usage.percent <= 100, usage.percent
        if hasattr(shutil, 'disk_usage'):
            # py >= 3.3, see: http://bugs.python.org/issue12442
            shutil_usage = shutil.disk_usage(os.getcwd())
            tolerance = 5 * 1024 * 1024  # 5MB
            self.assertEqual(usage.total, shutil_usage.total)
            self.assertAlmostEqual(usage.free, shutil_usage.free,
                                   delta=tolerance)
            if not MACOS_12PLUS:
                # see https://github.com/giampaolo/psutil/issues/2147
                self.assertAlmostEqual(usage.used, shutil_usage.used,
                                       delta=tolerance)

        # if path does not exist OSError ENOENT is expected across
        # all platforms
        fname = self.get_testfn()
        with self.assertRaises(FileNotFoundError):
            psutil.disk_usage(fname)

    @unittest.skipIf(not ASCII_FS, "not an ASCII fs")
    def test_disk_usage_unicode(self):
        # See: https://github.com/giampaolo/psutil/issues/416
        with self.assertRaises(UnicodeEncodeError):
            psutil.disk_usage(UNICODE_SUFFIX)

    def test_disk_usage_bytes(self):
        psutil.disk_usage(b'.')

    def test_disk_partitions(self):
        def check_ntuple(nt):
            self.assertIsInstance(nt.device, str)
            self.assertIsInstance(nt.mountpoint, str)
            self.assertIsInstance(nt.fstype, str)
            self.assertIsInstance(nt.opts, str)
            self.assertIsInstance(nt.maxfile, (int, type(None)))
            self.assertIsInstance(nt.maxpath, (int, type(None)))
            if nt.maxfile is not None and not GITHUB_ACTIONS:
                self.assertGreater(nt.maxfile, 0)
            if nt.maxpath is not None:
                self.assertGreater(nt.maxpath, 0)

        # all = False
        ls = psutil.disk_partitions(all=False)
        self.assertTrue(ls, msg=ls)
        for disk in ls:
            check_ntuple(disk)
            if WINDOWS and 'cdrom' in disk.opts:
                continue
            if not POSIX:
                assert os.path.exists(disk.device), disk
            else:
                # we cannot make any assumption about this, see:
                # http://goo.gl/p9c43
                disk.device
            # on modern systems mount points can also be files
            assert os.path.exists(disk.mountpoint), disk
            assert disk.fstype, disk

        # all = True
        ls = psutil.disk_partitions(all=True)
        self.assertTrue(ls, msg=ls)
        for disk in psutil.disk_partitions(all=True):
            check_ntuple(disk)
            if not WINDOWS and disk.mountpoint:
                try:
                    os.stat(disk.mountpoint)
                except OSError as err:
                    if GITHUB_ACTIONS and MACOS and err.errno == errno.EIO:
                        continue
                    # http://mail.python.org/pipermail/python-dev/
                    #     2012-June/120787.html
                    if err.errno not in (errno.EPERM, errno.EACCES):
                        raise
                else:
                    assert os.path.exists(disk.mountpoint), disk

        # ---

        def find_mount_point(path):
            path = os.path.abspath(path)
            while not os.path.ismount(path):
                path = os.path.dirname(path)
            return path.lower()

        mount = find_mount_point(__file__)
        mounts = [x.mountpoint.lower() for x in
                  psutil.disk_partitions(all=True) if x.mountpoint]
        self.assertIn(mount, mounts)

    @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'),
                     '/proc/diskstats not available on this linux version')
    @unittest.skipIf(CI_TESTING and not psutil.disk_io_counters(),
                     "unreliable on CI")  # no visible disks
    def test_disk_io_counters(self):
        def check_ntuple(nt):
            self.assertEqual(nt[0], nt.read_count)
            self.assertEqual(nt[1], nt.write_count)
            self.assertEqual(nt[2], nt.read_bytes)
            self.assertEqual(nt[3], nt.write_bytes)
            if not (OPENBSD or NETBSD):
                self.assertEqual(nt[4], nt.read_time)
                self.assertEqual(nt[5], nt.write_time)
                if LINUX:
                    self.assertEqual(nt[6], nt.read_merged_count)
                    self.assertEqual(nt[7], nt.write_merged_count)
                    self.assertEqual(nt[8], nt.busy_time)
                elif FREEBSD:
                    self.assertEqual(nt[6], nt.busy_time)
            for name in nt._fields:
                assert getattr(nt, name) >= 0, nt

        ret = psutil.disk_io_counters(perdisk=False)
        assert ret is not None, "no disks on this system?"
        check_ntuple(ret)
        ret = psutil.disk_io_counters(perdisk=True)
        # make sure there are no duplicates
        self.assertEqual(len(ret), len(set(ret)))
        for key in ret:
            assert key, key
            check_ntuple(ret[key])

    def test_disk_io_counters_no_disks(self):
        # Emulate a case where no disks are installed, see:
        # https://github.com/giampaolo/psutil/issues/1062
        with mock.patch('psutil._psplatform.disk_io_counters',
                        return_value={}) as m:
            self.assertIsNone(psutil.disk_io_counters(perdisk=False))
            self.assertEqual(psutil.disk_io_counters(perdisk=True), {})
            assert m.called

class TestNetAPIs(PsutilTestCase):

    @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported')
    def test_net_io_counters(self):
        def check_ntuple(nt):
            self.assertEqual(nt[0], nt.bytes_sent)
            self.assertEqual(nt[1], nt.bytes_recv)
            self.assertEqual(nt[2], nt.packets_sent)
            self.assertEqual(nt[3], nt.packets_recv)
            self.assertEqual(nt[4], nt.errin)
            self.assertEqual(nt[5], nt.errout)
            self.assertEqual(nt[6], nt.dropin)
            self.assertEqual(nt[7], nt.dropout)
            assert nt.bytes_sent >= 0, nt
            assert nt.bytes_recv >= 0, nt
            assert nt.packets_sent >= 0, nt
            assert nt.packets_recv >= 0, nt
            assert nt.errin >= 0, nt
            assert nt.errout >= 0, nt
            assert nt.dropin >= 0, nt
            assert nt.dropout >= 0, nt

        ret = psutil.net_io_counters(pernic=False)
        check_ntuple(ret)
        ret = psutil.net_io_counters(pernic=True)
        self.assertNotEqual(ret, [])
        for key in ret:
            self.assertTrue(key)
            self.assertIsInstance(key, str)
            check_ntuple(ret[key])

    @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported')
    def test_net_io_counters_no_nics(self):
        # Emulate a case where no NICs are installed, see:
        # https://github.com/giampaolo/psutil/issues/1062
        with mock.patch('psutil._psplatform.net_io_counters',
                        return_value={}) as m:
            self.assertIsNone(psutil.net_io_counters(pernic=False))
            self.assertEqual(psutil.net_io_counters(pernic=True), {})
            assert m.called

    def test_net_if_addrs(self):
        nics = psutil.net_if_addrs()
        assert nics, nics

        nic_stats = psutil.net_if_stats()

        # Not reliable on all platforms (net_if_addrs() reports more
        # interfaces).
        # self.assertEqual(sorted(nics.keys()),
        #                  sorted(psutil.net_io_counters(pernic=True).keys()))

        families = set([socket.AF_INET, socket.AF_INET6, psutil.AF_LINK])
        for nic, addrs in nics.items():
            self.assertIsInstance(nic, str)
            self.assertEqual(len(set(addrs)), len(addrs))
            for addr in addrs:
                self.assertIsInstance(addr.family, int)
                self.assertIsInstance(addr.address, str)
                self.assertIsInstance(addr.netmask, (str, type(None)))
                self.assertIsInstance(addr.broadcast, (str, type(None)))
                self.assertIn(addr.family, families)
                if sys.version_info >= (3, 4) and not PYPY:
                    self.assertIsInstance(addr.family, enum.IntEnum)
                if nic_stats[nic].isup:
                    # Do not test binding to addresses of interfaces
                    # that are down
                    if addr.family == socket.AF_INET:
                        s = socket.socket(addr.family)
                        with contextlib.closing(s):
                            s.bind((addr.address, 0))
                    elif addr.family == socket.AF_INET6:
                        info = socket.getaddrinfo(
                            addr.address, 0, socket.AF_INET6,
                            socket.SOCK_STREAM, 0, socket.AI_PASSIVE)[0]
                        af, socktype, proto, canonname, sa = info
                        s = socket.socket(af, socktype, proto)
                        with contextlib.closing(s):
                            s.bind(sa)
                for ip in (addr.address, addr.netmask, addr.broadcast,
                           addr.ptp):
                    if ip is not None:
                        # TODO: skip AF_INET6 for now because I get:
                        # AddressValueError: Only hex digits permitted in
                        # u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0'
                        if addr.family != socket.AF_INET6:
                            check_net_address(ip, addr.family)
                # broadcast and ptp addresses are mutually exclusive
                if addr.broadcast:
                    self.assertIsNone(addr.ptp)
                elif addr.ptp:
                    self.assertIsNone(addr.broadcast)

        if BSD or MACOS or SUNOS:
            if hasattr(socket, "AF_LINK"):
                self.assertEqual(psutil.AF_LINK, socket.AF_LINK)
        elif LINUX:
            self.assertEqual(psutil.AF_LINK, socket.AF_PACKET)
        elif WINDOWS:
            self.assertEqual(psutil.AF_LINK, -1)

    def test_net_if_addrs_mac_null_bytes(self):
        # Simulate that the underlying C function returns an incomplete
        # MAC address. psutil is supposed to fill it with null bytes.
        # https://github.com/giampaolo/psutil/issues/786
        if POSIX:
            ret = [('em1', psutil.AF_LINK, '06:3d:29', None, None, None)]
        else:
            ret = [('em1', -1, '06-3d-29', None, None, None)]
        with mock.patch('psutil._psplatform.net_if_addrs',
                        return_value=ret) as m:
            addr = psutil.net_if_addrs()['em1'][0]
            assert m.called
            if POSIX:
                self.assertEqual(addr.address, '06:3d:29:00:00:00')
            else:
                self.assertEqual(addr.address, '06-3d-29-00-00-00')

    def test_net_if_stats(self):
        nics = psutil.net_if_stats()
        assert nics, nics
        all_duplexes = (psutil.NIC_DUPLEX_FULL,
                        psutil.NIC_DUPLEX_HALF,
                        psutil.NIC_DUPLEX_UNKNOWN)
        for name, stats in nics.items():
            self.assertIsInstance(name, str)
            isup, duplex, speed, mtu, flags = stats
            self.assertIsInstance(isup, bool)
            self.assertIn(duplex, all_duplexes)
            self.assertIn(duplex, all_duplexes)
            self.assertGreaterEqual(speed, 0)
            self.assertGreaterEqual(mtu, 0)
            self.assertIsInstance(flags, str)

    @unittest.skipIf(not (LINUX or BSD or MACOS),
                     "LINUX or BSD or MACOS specific")
    def test_net_if_stats_enodev(self):
        # See: https://github.com/giampaolo/psutil/issues/1279
        with mock.patch('psutil._psutil_posix.net_if_mtu',
                        side_effect=OSError(errno.ENODEV, "")) as m:
            ret = psutil.net_if_stats()
            self.assertEqual(ret, {})
            assert m.called

class TestSensorsAPIs(PsutilTestCase):

    @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported")
    def test_sensors_temperatures(self):
        temps = psutil.sensors_temperatures()
        for name, entries in temps.items():
            self.assertIsInstance(name, str)
            for entry in entries:
                self.assertIsInstance(entry.label, str)
                if entry.current is not None:
                    self.assertGreaterEqual(entry.current, 0)
                if entry.high is not None:
                    self.assertGreaterEqual(entry.high, 0)
                if entry.critical is not None:
                    self.assertGreaterEqual(entry.critical, 0)

    @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported")
    def test_sensors_temperatures_fahreneit(self):
        d = {'coretemp': [('label', 50.0, 60.0, 70.0)]}
        with mock.patch("psutil._psplatform.sensors_temperatures",
                        return_value=d) as m:
            temps = psutil.sensors_temperatures(
                fahrenheit=True)['coretemp'][0]
            assert m.called
            self.assertEqual(temps.current, 122.0)
            self.assertEqual(temps.high, 140.0)
            self.assertEqual(temps.critical, 158.0)

    @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported")
    @unittest.skipIf(not HAS_BATTERY, "no battery")
    def test_sensors_battery(self):
        ret = psutil.sensors_battery()
        self.assertGreaterEqual(ret.percent, 0)
        self.assertLessEqual(ret.percent, 100)
        if ret.secsleft not in (psutil.POWER_TIME_UNKNOWN,
                                psutil.POWER_TIME_UNLIMITED):
            self.assertGreaterEqual(ret.secsleft, 0)
        else:
            if ret.secsleft == psutil.POWER_TIME_UNLIMITED:
                self.assertTrue(ret.power_plugged)
        self.assertIsInstance(ret.power_plugged, bool)

    @unittest.skipIf(not HAS_SENSORS_FANS, "not supported")
    def test_sensors_fans(self):
        fans = psutil.sensors_fans()
        for name, entries in fans.items():
            self.assertIsInstance(name, str)
            for entry in entries:
                self.assertIsInstance(entry.label, str)
                self.assertIsInstance(entry.current, (int, long))
                self.assertGreaterEqual(entry.current, 0)

if __name__ == '__main__':
    from psutil.tests.runner import run_from_name
    run_from_name(__file__)


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Sci blog jekyll theme">
    <meta name="author" content="AIR RAYA Group">
    <link href='/MyBlog/img/favicon.ico' type='image/icon' rel='shortcut icon'/>

    <title>泽民博客 | Jekyll theme</title>

    <link rel="stylesheet" href="/MyBlog/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <link rel="stylesheet" href="/MyBlog/css/font-awesome.min.css">
    <link href="/MyBlog/css/simple-sidebar.css" rel="stylesheet">
	<link href="/MyBlog/css/classic-10_7.css" rel="stylesheet" type="text/css">

    <link href="/MyBlog/css/style.css" rel="stylesheet">
    <link href="/MyBlog/css/pygments.css" rel="stylesheet">

 <link href="/MyBlog/css/front.css" rel="stylesheet" type="text/css">
 <link href="/MyBlog/css/Josefin_Slab.css" rel="stylesheet" type="text/css">
<link href="/MyBlog/css/Architects_Daughter.css" rel="stylesheet" type="text/css">
<link href="/MyBlog/css/Schoolbell.css" rel="stylesheet" type="text/css">
<link href="/MyBlog/css/Codystar.css" rel="stylesheet" type="text/css">

<link href="/MyBlog/css/calendar/common.css" type="text/css"  rel="stylesheet">

    <link rel="stylesheet" href="/MyBlog/katex/katex.css">

                        Home

                    About

                    Services

                    Portfolio

                    Events

                    Blog

                    FAQ

                    Contact

                        泽民博客
                        ☰ Menu

sync.WaitGroup 实现逻辑和源码解析

 by 夏泽民 <time datetime="2020-03-04T00:00:00+08:00" itemprop="datePublished"> Mar 4, 2020</time>

方便的并发,是Golang的一大特色优势,而使用并发,对sync包的WaitGroup不会陌生。WaitGroup主要用来做Golang并发实例即Goroutine的等待,当使用go启动多个并发程序,通过waitgroup可以等待所有go程序结束后再执行后面的代码逻辑,比如:

func Main() {

    wg := sync.WaitGroup{}

    for i := 0; i < 10; i++ {

        wg.Add(1)

        go func() {

            defer wg.Done()

            time.Sleep(10 * time.Second)

        }()

}

wg.Wait() // 等待在此,等所有go func里都执行了Done()才会退出 }

https://juejin.im/post/5e5b62f86fb9a07cb1578fda

实现原理

WaitGroup对外提供三个方法,Add(int),Done()和Wait(), 其中Done()是调用了Add(-1),一般使用方法是,先统一Add,在goroutine里并发的Done,然后Wait。

WaitGroup主要维护了2个计数器,一个是请求计数器 v,一个是等待计数器 w,二者组成一个64bit的值,请求计数器占高32bit,等待计数器占低32bit。

每次Add执行,请求计数器v加1,Done方法执行,请求计数器减1,v为0时通过信号量唤醒Wait()。

那么等待计数器拿来干嘛?是因为同一个实例的Wait()方法支持多处调用,每一次Wait()方法执行,等待计数器 w 就会加1,而当请求计数器v为0触发Wait()时,要根据w的数量发送w份的信号量,正确的触发所有的Wait(),这虽然不是常用的一个特性,但是在一些特殊场合是有用处的(比如多个并发都依赖于WaitGroup的实例的结束信号来进行下一个action),演示代码如下:

func main() {

  wg := sync.WaitGroup{}

  for i := 0; i < 10; i++ {

    wg.Add(1)

    go func() {

      defer wg.Done()

    }()

  }

  time.Sleep(2 * time.Second)

  for j := 0; j < 3; j++ {

    go func(i int) {

      // 3个地方调用Wait(),通过等待j计时器,每个Wati都会被hu唤醒

      wg.Wait()

      fmt.Println("wait done now ", i)

    }(j)

  }

  time.Sleep(10 * time.Second)

  return

}

/*

输出如下,数字出现的顺序随机

wait done now  1

wait done now  0

wait done now  2

*/

复制代码同时,WaitGroup里还对使用逻辑进行了严格的检查,比如Wait()一旦开始不能Add().

下面是带注释的代码,去掉了不影响代码逻辑的trace部分:

func (wg *WaitGroup) Add(delta int) {

    statep := wg.state()

    // 更新statep,statep将在wait和add中通过原子操作一起使用

    state := atomic.AddUint64(statep, uint64(delta)«32)

    v := int32(state » 32)

    w := uint32(state)

        if v < 0 {

        panic("sync: negative WaitGroup counter")

    }

    if w != 0 && delta > 0 && v == int32(delta) {

        // wait不等于0说明已经执行了Wait,此时不容许Add

        panic("sync: WaitGroup misuse: Add called concurrently with Wait")

    }

    // 正常情况,Add会让v增加,Done会让v减少,如果没有全部Done掉,此处v总是会大于0的,直到v为0才往下走

    // 而w代表是有多少个goruntine在等待done的信号,wait中通过compareAndSwap对这个w进行加1

     if v > 0 || w == 0 {

        return

    }

    // This goroutine has set counter to 0 when waiters > 0.

    // Now there can't be concurrent mutations of state:

    // - Adds must not happen concurrently with Wait,

    // - Wait does not increment waiters if it sees counter == 0.

    // Still do a cheap sanity check to detect WaitGroup misuse.

    // 当v为0(Done掉了所有)或者w不为0(已经开始等待)才会到这里,但是在这个过程中又有一次Add,导致statep变化,panic

    if *statep != state {

        panic("sync: WaitGroup misuse: Add called concurrently with Wait")

    }

    // Reset waiters count to 0.

    // 将statep清0,在Wait中通过这个值来保护信号量发出后还对这个Waitgroup进行操作

    *statep = 0

    // 将信号量发出,触发wait结束

    for ; w != 0; w– {

        runtime_Semrelease(&wg.sema, false)

    }

}

// Done decrements the WaitGroup counter by one.

func (wg *WaitGroup) Done() {

    wg.Add(-1)

}

// Wait blocks until the WaitGroup counter is zero.

func (wg *WaitGroup) Wait() {

    statep := wg.state()

        for {

        state := atomic.LoadUint64(statep)

        v := int32(state » 32)

        w := uint32(state)

        if v == 0 {

            // Counter is 0, no need to wait.

            if race.Enabled {

                race.Enable()

                race.Acquire(unsafe.Pointer(wg))

            }

            return

        }

        // Increment waiters count.

        // 如果statep和state相等,则增加等待计数,同时进入if等待信号量

        // 此处做CAS,主要是防止多个goroutine里进行Wait()操作,每有一个goroutine进行了wait,等待计数就加1

        // 如果这里不相等,说明statep,在 从读出来 到 CAS比较 的这个时间区间内,被别的goroutine改写了,那么不进入if,回去再读一次,这样写避免用锁,更高效些

        if atomic.CompareAndSwapUint64(statep, state, state+1) {

            if race.Enabled && w == 0 {

                // Wait must be synchronized with the first Add.

                // Need to model this is as a write to race with the read in Add.

                // As a consequence, can do the write only for the first waiter,

                // otherwise concurrent Waits will race with each other.

                race.Write(unsafe.Pointer(&wg.sema))

            }

            // 等待信号量

            runtime_Semacquire(&wg.sema)

            // 信号量来了,代表所有Add都已经Done

            if *statep != 0 {

                // 走到这里,说明在所有Add都已经Done后,触发信号量后,又被执行了Add

                panic("sync: WaitGroup is reused before previous Wait has returned")

            }

            return

        }

    }

}

                Category golang

<link rel="stylesheet" href="/MyBlog/css/default.css">


text:
/*
 * -----------------------------------------------------------------
 * $Revision: 4074 $
 * $Date: 2014-04-23 14:13:52 -0700 (Wed, 23 Apr 2014) $
 * -----------------------------------------------------------------
 * Programmer(s): Radu Serban @ LLNL
 * -----------------------------------------------------------------
 * This example solves a 2D elliptic PDE
 *
 *    d^2 u / dx^2 + d^2 u / dy^2 = u^3 - u - 2.0
 *
 * subject to homogeneous Dirichelt boundary conditions.
 * The PDE is discretized on a uniform NX+2 by NY+2 grid with
 * central differencing, and with boundary values eliminated,
 * leaving an system of size NEQ = NX*NY.
 * The nonlinear system is solved by KINSOL using the BAND linear
 * solver.
 * -----------------------------------------------------------------
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <kinsol/kinsol.h>
#include <kinsol/kinsol_band.h>
#include <nvector/nvector_serial.h>
#include <sundials/sundials_types.h>
#include <sundials/sundials_math.h>

/* Problem Constants */

#define NX   31             /* no. of points in x direction */
#define NY   31             /* no. of points in y direction */
#define NEQ  NX*NY          /* problem dimension */

#define SKIP 3              /* no. of points skipped for printing */

#define FTOL RCONST(1.e-12) /* function tolerance */

#define ZERO RCONST(0.0)
#define ONE  RCONST(1.0)
#define TWO  RCONST(2.0)

/* IJth is defined in order to isolate the translation from the
   mathematical 2-dimensional structure of the dependent variable vector
   to the underlying 1-dimensional storage.
   IJth(vdata,i,j) references the element in the vdata array for
   u at mesh point (i,j), where 1 <= i <= NX, 1 <= j <= NY.
   The vdata array is obtained via the macro call vdata = NV_DATA_S(v),
   where v is an N_Vector.
   The variables are ordered by the y index j, then by the x index i. */

#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*NY])

/* Private functions */

static int func(N_Vector u, N_Vector f, void *user_data);
static void PrintOutput(N_Vector u);
static void PrintFinalStats(void *kmem);
static int check_flag(void *flagvalue, char *funcname, int opt);

/*
 *--------------------------------------------------------------------
 * MAIN PROGRAM
 *--------------------------------------------------------------------
 */

int main()
{
  realtype fnormtol, fnorm;
  N_Vector y, scale;
  int mset, msubset, flag;
  void *kmem;

  y = scale = NULL;
  kmem = NULL;

  /* -------------------------
   * Print problem description
   * ------------------------- */

  printf("\n2D elliptic PDE on unit square\n");
  printf("   d^2 u / dx^2 + d^2 u / dy^2 = u^3 - u + 2.0\n");
  printf(" + homogeneous Dirichlet boundary conditions\n\n");
  printf("Solution method: Modified Newton with band linear solver\n");
  printf("Problem size: %2ld x %2ld = %4ld\n", (long int) NX, (long int) NY, (long int) NEQ);

  /* --------------------------------------
   * Create vectors for solution and scales
   * -------------------------------------- */

  y = N_VNew_Serial(NEQ);
  if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);

  scale = N_VNew_Serial(NEQ);
  if (check_flag((void *)scale, "N_VNew_Serial", 0)) return(1);

  /* -----------------------------------------
   * Initialize and allocate memory for KINSOL
   * ----------------------------------------- */

  kmem = KINCreate();
  if (check_flag((void *)kmem, "KINCreate", 0)) return(1);

  /* y is used as a template */

  flag = KINInit(kmem, func, y);
  if (check_flag(&flag, "KINInit", 1)) return(1);

  /* -------------------
   * Set optional inputs
   * ------------------- */

  /* Specify stopping tolerance based on residual */

  fnormtol  = FTOL;
  flag = KINSetFuncNormTol(kmem, fnormtol);
  if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);

  /* -------------------------
   * Attach band linear solver
   * ------------------------- */

  flag = KINBand(kmem, NEQ, NX, NX);
  if (check_flag(&flag, "KINBand", 1)) return(1);

  /* ------------------------------
   * Parameters for Modified Newton
   * ------------------------------ */

  /* Force a Jacobian re-evaluation every mset iterations */
  mset = 100;
  flag = KINSetMaxSetupCalls(kmem, mset);
  if (check_flag(&flag, "KINSetMaxSetupCalls", 1)) return(1);

  /* Every msubset iterations, test if a Jacobian evaluation
     is necessary */
  msubset = 1;
  flag = KINSetMaxSubSetupCalls(kmem, msubset);
  if (check_flag(&flag, "KINSetMaxSubSetupCalls", 1)) return(1);

  /* -------------
   * Initial guess
   * ------------- */

  N_VConst_Serial(ZERO, y);

  /* ----------------------------
   * Call KINSol to solve problem
   * ---------------------------- */

  /* No scaling used */
  N_VConst_Serial(ONE,scale);

  /* Call main solver */
  flag = KINSol(kmem,           /* KINSol memory block */
                y,              /* initial guess on input; solution vector */
                KIN_LINESEARCH, /* global strategy choice */
                scale,          /* scaling vector, for the variable cc */
                scale);         /* scaling vector for function values fval */
  if (check_flag(&flag, "KINSol", 1)) return(1);

  /* ------------------------------------
   * Print solution and solver statistics
   * ------------------------------------ */

  /* Get scaled norm of the system function */

  flag = KINGetFuncNorm(kmem, &fnorm);
  if (check_flag(&flag, "KINGetfuncNorm", 1)) return(1);

  printf("\nComputed solution (||F|| = %g):\n\n",fnorm);
  PrintOutput(y);

  PrintFinalStats(kmem);

  /* -----------
   * Free memory
   * ----------- */

  N_VDestroy_Serial(y);
  N_VDestroy_Serial(scale);
  KINFree(&kmem);

  return(0);
}

/*
 *--------------------------------------------------------------------
 * PRIVATE FUNCTIONS
 *--------------------------------------------------------------------
 */

/*
 * System function
 */

static int func(N_Vector u, N_Vector f, void *user_data)
{
  realtype dx, dy, hdiff, vdiff;
  realtype hdc, vdc;
  realtype uij, udn, uup, ult, urt;
  realtype *udata, *fdata;
  realtype x,y;

  int i, j;

  dx = ONE/(NX+1);
  dy = ONE/(NY+1);
  hdc = ONE/(dx*dx);
  vdc = ONE/(dy*dy);

  udata = NV_DATA_S(u);
  fdata = NV_DATA_S(f);

  for (j=1; j <= NY; j++) {

    y = j*dy;

    for (i=1; i <= NX; i++) {

      x = i*dx;

      /* Extract u at x_i, y_j and four neighboring points */

      uij = IJth(udata, i, j);
      udn = (j == 1)  ? ZERO : IJth(udata, i, j-1);
      uup = (j == NY) ? ZERO : IJth(udata, i, j+1);
      ult = (i == 1)  ? ZERO : IJth(udata, i-1, j);
      urt = (i == NX) ? ZERO : IJth(udata, i+1, j);

      /* Evaluate diffusion components */

      hdiff = hdc*(ult - TWO*uij + urt);
      vdiff = vdc*(uup - TWO*uij + udn);

      /* Set residual at x_i, y_j */

      IJth(fdata, i, j) = hdiff + vdiff + uij - uij*uij*uij + 2.0;

    }

  }

  return(0);
}

/*
 * Print solution at selected points
 */

static void PrintOutput(N_Vector u)
{
  int i, j;
  realtype dx, dy, x, y;
  realtype *udata;

  dx = ONE/(NX+1);
  dy = ONE/(NY+1);

  udata =  NV_DATA_S(u);

  printf("            ");
  for (i=1; i<=NX; i+= SKIP) {
    x = i*dx;
#if defined(SUNDIALS_EXTENDED_PRECISION)
      printf("%-8.5Lf ", x);
#elif defined(SUNDIALS_DOUBLE_PRECISION)
      printf("%-8.5f ", x);
#else
      printf("%-8.5f ", x);
#endif
  }
  printf("\n\n");

  for (j=1; j<=NY; j+= SKIP) {
    y = j*dy;
#if defined(SUNDIALS_EXTENDED_PRECISION)
      printf("%-8.5Lf    ", y);
#elif defined(SUNDIALS_DOUBLE_PRECISION)
      printf("%-8.5f    ", y);
#else
      printf("%-8.5f    ", y);
#endif
    for (i=1; i<=NX; i+= SKIP) {
#if defined(SUNDIALS_EXTENDED_PRECISION)
      printf("%-8.5Lf ", IJth(udata,i,j));
#elif defined(SUNDIALS_DOUBLE_PRECISION)
      printf("%-8.5f ", IJth(udata,i,j));
#else
      printf("%-8.5f ", IJth(udata,i,j));
#endif
    }
    printf("\n");
  }
}

/*
 * Print final statistics
 */

static void PrintFinalStats(void *kmem)
{
  long int nni, nfe, nje, nfeD;
  long int lenrw, leniw, lenrwB, leniwB;
  long int nbcfails, nbacktr;
  int flag;

  /* Main solver statistics */

  flag = KINGetNumNonlinSolvIters(kmem, &nni);
  check_flag(&flag, "KINGetNumNonlinSolvIters", 1);
  flag = KINGetNumFuncEvals(kmem, &nfe);
  check_flag(&flag, "KINGetNumFuncEvals", 1);

  /* Linesearch statistics */

  flag = KINGetNumBetaCondFails(kmem, &nbcfails);
  check_flag(&flag, "KINGetNumBetacondFails", 1);
  flag = KINGetNumBacktrackOps(kmem, &nbacktr);
  check_flag(&flag, "KINGetNumBacktrackOps", 1);

  /* Main solver workspace size */

  flag = KINGetWorkSpace(kmem, &lenrw, &leniw);
  check_flag(&flag, "KINGetWorkSpace", 1);

  /* Band linear solver statistics */

  flag = KINDlsGetNumJacEvals(kmem, &nje);
  check_flag(&flag, "KINDlsGetNumJacEvals", 1);
  flag = KINDlsGetNumFuncEvals(kmem, &nfeD);
  check_flag(&flag, "KINDlsGetNumFuncEvals", 1);

  /* Band linear solver workspace size */

  flag = KINDlsGetWorkSpace(kmem, &lenrwB, &leniwB);
  check_flag(&flag, "KINDlsGetWorkSpace", 1);

  printf("\nFinal Statistics.. \n\n");
  printf("nni      = %6ld    nfe     = %6ld \n", nni, nfe);
  printf("nbcfails = %6ld    nbacktr = %6ld \n", nbcfails, nbacktr);
  printf("nje      = %6ld    nfeB    = %6ld \n", nje, nfeD);
  printf("\n");
  printf("lenrw    = %6ld    leniw   = %6ld \n", lenrw, leniw);
  printf("lenrwB   = %6ld    leniwB  = %6ld \n", lenrwB, leniwB);

}

/*
 * Check function return value...
 *    opt == 0 means SUNDIALS function allocates memory so check if
 *             returned NULL pointer
 *    opt == 1 means SUNDIALS function returns a flag so check if
 *             flag >= 0
 *    opt == 2 means function allocates memory so check if returned
 *             NULL pointer
 */

static int check_flag(void *flagvalue, char *funcname, int opt)
{
  int *errflag;

  /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
  if (opt == 0 && flagvalue == NULL) {
    fprintf(stderr,
            "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
	    funcname);
    return(1);
  }

  /* Check if flag < 0 */
  else if (opt == 1) {
    errflag = (int *) flagvalue;
    if (*errflag < 0) {
      fprintf(stderr,
              "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
	      funcname, *errflag);
      return(1);
    }
  }

  /* Check if function returned NULL pointer - no memory allocated */
  else if (opt == 2 && flagvalue == NULL) {
    fprintf(stderr,
            "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n",
	    funcname);
    return(1);
  }

  return(0);
}


text:
module Dynflow
  module Flows
    class Sequence < AbstractComposed

      protected

      def add_to_sequence(satisfying_flows, dependent_flow)
        # the flows are already in sequence, we don't need to do anything extra
        self << dependent_flow
      end
    end
  end
end


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>interactive-data-core</artifactId>
    <name>Interactive Data Core</name>
    <description>Interactive Data API declaration that can be implemented by various implementations</description>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.github.mrgoro</groupId>
        <artifactId>interactive-data</artifactId>
        <version>1.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.github.mrgoro</groupId>
            <artifactId>interactive-data-processors</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </dependency>
    </dependencies>

</project>


text:
/**
 * An abstract service that can be used to get and set the title of a current HTML document.
 */
export abstract class Title {

  abstract getTitle(): string;

  abstract setTitle(title: string): void;

}


text:
using Core.Queries;
using Marten;
using Marten.Pagination;

namespace Tickets.Reservations.GettingReservations;

public record GetReservations(
    int PageNumber,
    int PageSize
): IQuery<IPagedList<ReservationShortInfo>>
{
    public static GetReservations Create(int pageNumber = 1, int pageSize = 20)
    {
        if (pageNumber <= 0)
            throw new ArgumentOutOfRangeException(nameof(pageNumber));
        if (pageSize is <= 0 or > 100)
            throw new ArgumentOutOfRangeException(nameof(pageSize));

        return new GetReservations(pageNumber, pageSize);
    }
}

internal class HandleGetReservations:
    IQueryHandler<GetReservations, IPagedList<ReservationShortInfo>>
{
    private readonly IDocumentSession querySession;

    public HandleGetReservations(IDocumentSession querySession)
    {
        this.querySession = querySession;
    }

    public Task<IPagedList<ReservationShortInfo>> Handle(
        GetReservations query,
        CancellationToken cancellationToken
    ) =>
        querySession.Query<ReservationShortInfo>()
            .ToPagedListAsync(query.PageNumber, query.PageSize, cancellationToken);
}